TextureAttrib::_implicit_sort

This commit is contained in:
David Rose 2008-04-10 00:45:43 +00:00
parent 61b849ee15
commit a667e91dce
12 changed files with 303 additions and 201 deletions

View File

@ -487,17 +487,13 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
}
InternalName *name = _shader->_var_spec[i]._name;
int texslot = _shader->_var_spec[i]._append_uv;
if (texslot >= 0) {
const Geom::ActiveTextureStages &active_stages =
gsg->_state._texture->get_on_stages();
if (texslot < (int)active_stages.size()) {
TextureStage *stage = active_stages[texslot];
InternalName *texname = stage->get_texcoord_name();
if (name == InternalName::get_texcoord()) {
name = texname;
} else if (texname != InternalName::get_texcoord()) {
name = name->append(texname->get_basename());
}
if (texslot >= 0 && texslot < gsg->_state._texture->get_num_on_stages()) {
TextureStage *stage = gsg->_state._texture->get_on_stage(texslot);
InternalName *texname = stage->get_texcoord_name();
if (name == InternalName::get_texcoord()) {
name = texname;
} else if (texname != InternalName::get_texcoord()) {
name = name->append(texname->get_basename());
}
}
if (gsg->_data_reader->get_array_info(name, array_reader, num_values, numeric_type, start, stride)) {

View File

@ -1988,16 +1988,11 @@ update_standard_vertex_arrays(bool force) {
// Now set up each of the active texture coordinate stages--or at
// least those for which we're not generating texture coordinates
// automatically.
const Geom::ActiveTextureStages &active_stages =
_effective_texture->get_on_ff_stages();
const Geom::NoTexCoordStages &no_texcoords =
_effective_tex_gen->get_no_texcoords();
int max_stage_index = (int)active_stages.size();
int max_stage_index = _effective_texture->get_num_on_ff_stages();
int stage_index = 0;
while (stage_index < max_stage_index) {
TextureStage *stage = active_stages[stage_index];
if (no_texcoords.find(stage) == no_texcoords.end()) {
TextureStage *stage = _effective_texture->get_on_ff_stage(stage_index);
if (!_effective_tex_gen->has_gen_texcoord_stage(stage)) {
// This stage is not one of the stages that doesn't need
// texcoords issued for it.
const InternalName *name = stage->get_texcoord_name();
@ -2089,17 +2084,12 @@ update_standard_vertex_arrays(bool force) {
// Now set up each of the active texture coordinate stages--or at
// least those for which we're not generating texture coordinates
// automatically.
const Geom::ActiveTextureStages &active_stages =
_effective_texture->get_on_ff_stages();
const Geom::NoTexCoordStages &no_texcoords =
_effective_tex_gen->get_no_texcoords();
int max_stage_index = (int)active_stages.size();
int max_stage_index = _effective_texture->get_num_on_ff_stages();
int stage_index = 0;
while (stage_index < max_stage_index) {
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
TextureStage *stage = active_stages[stage_index];
if (no_texcoords.find(stage) == no_texcoords.end()) {
TextureStage *stage = _effective_texture->get_on_ff_stage(stage_index);
if (!_effective_tex_gen->has_gen_texcoord_stage(stage)) {
// This stage is not one of the stages that doesn't need
// texcoords issued for it.
const InternalName *name = stage->get_texcoord_name();

View File

@ -260,17 +260,13 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg,
if (p == 0) continue;
InternalName *name = _shader->_var_spec[i]._name;
int texslot = _shader->_var_spec[i]._append_uv;
if (texslot >= 0) {
const Geom::ActiveTextureStages &active_stages =
gsg->_state._texture->get_on_stages();
if (texslot < (int)active_stages.size()) {
TextureStage *stage = active_stages[texslot];
InternalName *texname = stage->get_texcoord_name();
if (name == InternalName::get_texcoord()) {
name = texname;
} else if (texname != InternalName::get_texcoord()) {
name = name->append(texname->get_basename());
}
if (texslot >= 0 && texslot < gsg->_state._texture->get_num_on_stages()) {
TextureStage *stage = gsg->_state._texture->get_on_stage(texslot);
InternalName *texname = stage->get_texcoord_name();
if (name == InternalName::get_texcoord()) {
name = texname;
} else if (texname != InternalName::get_texcoord()) {
name = name->append(texname->get_basename());
}
}
if (gsg->_data_reader->get_array_info(name,

View File

@ -158,10 +158,6 @@ public:
static UpdateSeq get_next_modified();
public:
typedef pvector< PT(TextureStage) > ActiveTextureStages;
typedef pset<TextureStage *> NoTexCoordStages;
private:
class CData;

View File

@ -26,6 +26,10 @@
#include "pandabase.h"
#include "config_mesadisplay.h"
// This stuff seems to crash with Mesa.
#undef HAVE_CG
#undef HAVE_CGGL
#ifdef MESA_MGL
#define GLP(name) mgl##name
#define GLUP(name) mglu##name

View File

@ -66,20 +66,6 @@ get_geom_rendering(int geom_rendering) const {
return geom_rendering | _geom_rendering;
}
////////////////////////////////////////////////////////////////////
// Function: TexGenAttrib::get_no_texcoords
// Access: Public
// Description: Returns the set of TextureStages that have texture
// coordinates computed for them, and hence do not need
// to have texture coordinates sent from the Geom. This
// is, of course, the set of TextureStages that is
// listed in the attrib (except for those listed with M_off).
////////////////////////////////////////////////////////////////////
INLINE const Geom::NoTexCoordStages &TexGenAttrib::
get_no_texcoords() const {
return _no_texcoords;
}
////////////////////////////////////////////////////////////////////
// Function: TexGenAttrib::get_light_vectors
// Access: Public

View File

@ -216,6 +216,20 @@ get_mode(TextureStage *stage) const {
return M_off;
}
////////////////////////////////////////////////////////////////////
// Function: TexGenAttrib::has_gen_texcoord_stage
// Access: Published
// Description: Returns true if the indicated TextureStage will have
// texture coordinates generated for it automatically
// (and thus there is no need to upload the texture
// coordinates encoded in the vertices).
////////////////////////////////////////////////////////////////////
bool TexGenAttrib::
has_gen_texcoord_stage(TextureStage *stage) const {
NoTexCoordStages::const_iterator mi = _no_texcoords.find(stage);
return (mi != _no_texcoords.end());
}
////////////////////////////////////////////////////////////////////
// Function: TexGenAttrib::get_source_name
// Access: Published

View File

@ -64,6 +64,7 @@ PUBLISHED:
bool is_empty() const;
bool has_stage(TextureStage *stage) const;
Mode get_mode(TextureStage *stage) const;
bool has_gen_texcoord_stage(TextureStage *stage) const;
string get_source_name(TextureStage *stage) const;
NodePath get_light(TextureStage *stage) const;
const TexCoord3f &get_constant_value(TextureStage *stage) const;
@ -71,8 +72,6 @@ PUBLISHED:
INLINE int get_geom_rendering(int geom_rendering) const;
public:
INLINE const Geom::NoTexCoordStages &get_no_texcoords() const;
typedef pset<TextureStage *> LightVectors;
INLINE const LightVectors &get_light_vectors() const;
@ -106,7 +105,8 @@ private:
// coordinates will not be needed from the Geom. It's redundant;
// it's almost the same set that is listed in _stages, above. It's
// just here as an optimization during rendering.
Geom::NoTexCoordStages _no_texcoords;
typedef pset<TextureStage *> NoTexCoordStages;
NoTexCoordStages _no_texcoords;
// This is another optimization during rendering; it lists the
// texture stages (if any) that use M_light_vector.

View File

@ -25,6 +25,7 @@
////////////////////////////////////////////////////////////////////
INLINE TextureAttrib::
TextureAttrib() {
_next_implicit_sort = 0;
_off_all_stages = false;
_sort_seq = UpdateSeq::old();
}
@ -39,6 +40,9 @@ TextureAttrib() {
INLINE TextureAttrib::
TextureAttrib(const TextureAttrib &copy) :
_on_stages(copy._on_stages),
_on_ff_stages(copy._on_ff_stages),
_ff_tc_index(copy._ff_tc_index),
_next_implicit_sort(copy._next_implicit_sort),
_off_stages(copy._off_stages),
_off_all_stages(copy._off_all_stages),
_on_textures(copy._on_textures),
@ -101,7 +105,7 @@ get_num_on_stages() const {
INLINE TextureStage *TextureAttrib::
get_on_stage(int n) const {
nassertr(n >= 0 && n < (int)_on_stages.size(), (TextureStage *)NULL);
return _on_stages[n];
return _on_stages[n]._stage;
}
////////////////////////////////////////////////////////////////////
@ -128,7 +132,7 @@ get_num_on_ff_stages() const {
INLINE TextureStage *TextureAttrib::
get_on_ff_stage(int n) const {
nassertr(n >= 0 && n < (int)_on_ff_stages.size(), (TextureStage *)NULL);
return _on_ff_stages[n];
return _on_ff_stages[n]._stage;
}
////////////////////////////////////////////////////////////////////
@ -231,32 +235,6 @@ is_identity() const {
return _on_stages.empty() && _off_stages.empty() && !_off_all_stages;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::get_on_stages
// Access: Public
// Description: Returns the complete list of stages defined within
// this TextureAttrib, suitable for passing to
// Geom::setup_multitexcoord_iterator().
////////////////////////////////////////////////////////////////////
INLINE const Geom::ActiveTextureStages &TextureAttrib::
get_on_stages() const {
return _on_stages;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::get_on_ff_stages
// Access: Public
// Description: Returns the complete list of stages defined within
// this TextureAttrib, including only those which are
// relevant to the classic fixed-function pipeline.
// The result is suitable for passing to
// Geom::setup_multitexcoord_iterator().
////////////////////////////////////////////////////////////////////
INLINE const Geom::ActiveTextureStages &TextureAttrib::
get_on_ff_stages() const {
return _on_ff_stages;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::check_sorted
// Access: Private
@ -273,3 +251,29 @@ check_sorted() const {
((TextureAttrib *)this)->sort_on_stages();
}
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::OnStageNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE TextureAttrib::OnStageNode::
OnStageNode(TextureStage *stage, unsigned int implicit_sort) :
_stage(stage),
_implicit_sort(implicit_sort)
{
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::OnStageNode::Comparison Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool TextureAttrib::OnStageNode::
operator < (const TextureAttrib::OnStageNode &other) const {
if (_stage->get_sort() != other._stage->get_sort()) {
return _stage->get_sort() < other._stage->get_sort();
}
return _implicit_sort < other._implicit_sort;
}

View File

@ -33,16 +33,17 @@ TypeHandle TextureAttrib::_type_handle;
// This STL Function object is used in filter_to_max(), below, to sort
// a list of TextureStages in reverse order by priority and, within
// priority, in order by sort.
class CompareTextureStagePriorities {
public:
bool operator ()(const TextureStage *a, const TextureStage *b) const {
if (a->get_priority() != b->get_priority()) {
return a->get_priority() > b->get_priority();
}
return a->get_sort() < b->get_sort();
bool TextureAttrib::CompareTextureStagePriorities::
operator () (const TextureAttrib::OnStageNode &a,
const TextureAttrib::OnStageNode &b) const {
if (a._stage->get_priority() != b._stage->get_priority()) {
return a._stage->get_priority() > b._stage->get_priority();
}
};
if (a._stage->get_sort() != b._stage->get_sort()) {
return a._stage->get_sort() > b._stage->get_sort();
}
return a._implicit_sort < b._implicit_sort;
}
////////////////////////////////////////////////////////////////////
@ -115,7 +116,7 @@ make_all_off() {
int TextureAttrib::
find_on_stage(const TextureStage *stage) const {
for (int n = 0; n < (int)_on_stages.size(); ++n) {
if (_on_stages[n] == stage) {
if (_on_stages[n]._stage == stage) {
return n;
}
}
@ -139,7 +140,8 @@ add_on_stage(TextureStage *stage, Texture *tex) const {
// If the insert was successful--we have added a new stage that
// wasn't present before--then add the stage to the linear list
// also.
attrib->_on_stages.push_back(stage);
attrib->_on_stages.push_back(OnStageNode(stage, attrib->_next_implicit_sort));
++(attrib->_next_implicit_sort);
// Also ensure it is removed from the off_stages list.
attrib->_off_stages.erase(stage);
@ -148,6 +150,16 @@ add_on_stage(TextureStage *stage, Texture *tex) const {
// If the insert was unsuccessful, it means there was already a
// definition for that stage. Replace it.
(*insert_result.first).second = tex;
// Also update the implicit sort.
OnStages::iterator si;
for (si = attrib->_on_stages.begin(); si != attrib->_on_stages.end(); ++si) {
if ((*si)._stage == stage) {
(*si)._implicit_sort = attrib->_next_implicit_sort;
++(attrib->_next_implicit_sort);
break;
}
}
}
// In either case, we now need to re-sort the attrib list.
@ -170,13 +182,16 @@ remove_on_stage(TextureStage *stage) const {
OnTextures::iterator ti = attrib->_on_textures.find(stage);
if (ti != attrib->_on_textures.end()) {
attrib->_on_textures.erase(ti);
OnStages::iterator si =
find(attrib->_on_stages.begin(), attrib->_on_stages.end(),
PT(TextureStage)(stage));
if (si != attrib->_on_stages.end()) {
attrib->_on_stages.erase(si);
attrib->_sort_seq = UpdateSeq::old();
OnStages::iterator si;
for (si = attrib->_on_stages.begin(); si != attrib->_on_stages.end(); ++si) {
if ((*si)._stage == stage) {
attrib->_on_stages.erase(si);
break;
}
}
attrib->_sort_seq = UpdateSeq::old();
}
return return_new(attrib);
@ -199,13 +214,15 @@ add_off_stage(TextureStage *stage) const {
OnTextures::iterator ti = attrib->_on_textures.find(stage);
if (ti != attrib->_on_textures.end()) {
attrib->_on_textures.erase(ti);
OnStages::iterator si =
find(attrib->_on_stages.begin(), attrib->_on_stages.end(),
PT(TextureStage)(stage));
if (si != attrib->_on_stages.end()) {
attrib->_on_stages.erase(si);
attrib->_sort_seq = UpdateSeq::old();
OnStages::iterator si;
for (si = attrib->_on_stages.begin(); si != attrib->_on_stages.end(); ++si) {
if ((*si)._stage == stage) {
attrib->_on_stages.erase(si);
break;
}
}
attrib->_sort_seq = UpdateSeq::old();
}
}
return return_new(attrib);
@ -240,25 +257,31 @@ unify_texture_stages(TextureStage *stage) const {
attrib->_off_all_stages = _off_all_stages;
bool any_changed = false;
OnTextures::const_iterator nti;
for (nti = _on_textures.begin(); nti != _on_textures.end(); ++nti) {
if ((*nti).first != stage &&
(*nti).first->get_name() == stage->get_name()) {
attrib->_on_textures[stage] = (*nti).second;
OnStages::const_iterator si;
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
TextureStage *this_stage = (*si)._stage;
Texture *tex = get_on_texture(this_stage);
nassertr(tex != (Texture *)NULL, this);
if (this_stage->get_name() == stage->get_name()) {
this_stage = stage;
any_changed = true;
}
bool inserted = attrib->_on_textures.insert(OnTextures::value_type(this_stage, tex)).second;
if (inserted) {
// If the texture was successfully inserted, it was the first
// appearance of this stage. Add it to the on_stages list.
attrib->_on_stages.push_back(OnStageNode(this_stage, (*si)._implicit_sort));
} else {
attrib->_on_textures.insert(*nti);
// If the texture was not successfully inserted, it was a
// duplicate texture stage. This should only be possible if we
// have just collapsed a stage.
nassertr(this_stage == stage, this);
}
}
// Now copy from _on_textures to the _on_stages list. We can't do
// this as we walk through the list the first pass, since we might
// have collapsed together multiple different stages.
for (nti = attrib->_on_textures.begin();
nti != attrib->_on_textures.end();
++nti) {
attrib->_on_stages.push_back((*nti).first);
}
attrib->_next_implicit_sort = _next_implicit_sort;
OffStages::const_iterator fsi;
for (fsi = _off_stages.begin(); fsi != _off_stages.end(); ++fsi) {
@ -323,11 +346,12 @@ filter_to_max(int max_texture_stages) const {
OnStages::const_iterator si;
for (si = priority_stages.begin(); si != priority_stages.end(); ++si) {
TextureStage *stage = (*si);
TextureStage *stage = (*si)._stage;
attrib->_on_textures[stage] = get_on_texture(stage);
}
attrib->_on_stages.swap(priority_stages);
attrib->_next_implicit_sort = _next_implicit_sort;
CPT(RenderAttrib) new_attrib = return_new(attrib);
@ -376,9 +400,9 @@ output(ostream &out) const {
}
}
OnStages::const_iterator li;
for (li = _on_stages.begin(); li != _on_stages.end(); ++li) {
TextureStage *stage = (*li);
OnStages::const_iterator si;
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
TextureStage *stage = (*si)._stage;
OnTextures::const_iterator ti = _on_textures.find(stage);
if (ti != _on_textures.end()) {
Texture *tex = (*ti).second;
@ -461,6 +485,8 @@ compare_to_impl(const RenderAttrib *other) const {
return (int)_off_all_stages - (int)ta->_off_all_stages;
}
// First, verify that the texture assigned to each stage is the
// same.
OnTextures::const_iterator li = _on_textures.begin();
OnTextures::const_iterator oli = ta->_on_textures.begin();
@ -489,6 +515,43 @@ compare_to_impl(const RenderAttrib *other) const {
return -1;
}
// Then, we also have to check the linear list of texture stages, to
// ensure primarily that the implicit sort numbers match between the
// two attribs. (If they did not, then a later call to
// texture_stage->set_sort() might make these attribs apply textures
// differently, even if they are the same now.)
check_sorted();
ta->check_sorted();
OnStages::const_iterator si = _on_stages.begin();
OnStages::const_iterator osi = ta->_on_stages.begin();
while (si != _on_stages.end() && osi != ta->_on_stages.end()) {
TextureStage *stage = (*si)._stage;
TextureStage *other_stage = (*osi)._stage;
if (stage != other_stage) {
return stage < other_stage ? -1 : 1;
}
int implicit_sort = (*si)._implicit_sort;
int other_implicit_sort = (*osi)._implicit_sort;
if (implicit_sort != other_implicit_sort) {
return implicit_sort < other_implicit_sort ? -1 : 1;
}
++si;
++osi;
}
if (si != _on_stages.end()) {
return 1;
}
if (osi != ta->_on_stages.end()) {
return -1;
}
// Finally, ensure that the set of off stages is the same.
OffStages::const_iterator fi = _off_stages.begin();
OffStages::const_iterator ofi = ta->_off_stages.begin();
@ -549,8 +612,14 @@ compose_impl(const RenderAttrib *other) const {
OnTextures::const_iterator bi = ta->_on_textures.begin();
OffStages::const_iterator ci = ta->_off_stages.begin();
// TextureStages that are kept from the original attrib are inserted
// into a_stages. Those that are inherited from the secondary
// attrib are inserted into b_stages.
pset<TextureStage *> a_stages;
pset<TextureStage *> b_stages;
// Create a new TextureAttrib that will hold the result.
TextureAttrib *new_attrib = new TextureAttrib;
TextureAttrib *attrib = new TextureAttrib;
while (ai != _on_textures.end() &&
bi != ta->_on_textures.end() &&
@ -559,8 +628,8 @@ compose_impl(const RenderAttrib *other) const {
if ((*ai).first < (*ci)) {
// Here is a stage that we have in the original, which is not
// present in the secondary.
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *ai);
new_attrib->_on_stages.push_back((*ai).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *ai);
a_stages.insert((*ai).first);
++ai;
} else if ((*ci) < (*ai).first) {
@ -578,14 +647,14 @@ compose_impl(const RenderAttrib *other) const {
} else if ((*bi).first < (*ai).first) {
// Here is a new stage we have in the secondary, that was not
// present in the original.
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *bi);
new_attrib->_on_stages.push_back((*bi).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
b_stages.insert((*bi).first);
++bi;
} else { // (*bi).first == (*ai).first
// Here is a stage we have in both.
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *bi);
new_attrib->_on_stages.push_back((*ai).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
b_stages.insert((*bi).first);
++ai;
++bi;
}
@ -595,21 +664,21 @@ compose_impl(const RenderAttrib *other) const {
if ((*ai).first < (*bi).first) {
// Here is a stage that we have in the original, which is not
// present in the secondary.
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *ai);
new_attrib->_on_stages.push_back((*ai).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *ai);
a_stages.insert((*ai).first);
++ai;
} else if ((*bi).first < (*ai).first) {
// Here is a new stage we have in the secondary, that was not
// present in the original.
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *bi);
new_attrib->_on_stages.push_back((*bi).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
b_stages.insert((*bi).first);
++bi;
} else {
// Here is a stage we have in both.
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *bi);
new_attrib->_on_stages.push_back((*ai).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
b_stages.insert((*bi).first);
++ai;
++bi;
}
@ -619,8 +688,8 @@ compose_impl(const RenderAttrib *other) const {
if ((*ai).first < (*ci)) {
// Here is a stage that we have in the original, which is not
// present in the secondary.
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *ai);
new_attrib->_on_stages.push_back((*ai).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *ai);
a_stages.insert((*ai).first);
++ai;
} else if ((*ci) < (*ai).first) {
@ -637,18 +706,49 @@ compose_impl(const RenderAttrib *other) const {
}
while (ai != _on_textures.end()) {
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *ai);
new_attrib->_on_stages.push_back((*ai).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *ai);
a_stages.insert((*ai).first);
++ai;
}
while (bi != ta->_on_textures.end()) {
new_attrib->_on_textures.insert(new_attrib->_on_textures.end(), *bi);
new_attrib->_on_stages.push_back((*bi).first);
attrib->_on_textures.insert(attrib->_on_textures.end(), *bi);
b_stages.insert((*bi).first);
++bi;
}
return return_new(new_attrib);
// Now we need to build up the linear list. We must put this in
// order so that the original stages are first, followed by the
// secondary stages. If a texture stage is listed in both, it
// receives the secondary sort.
OnStages::const_iterator asi;
for (asi = _on_stages.begin(); asi != _on_stages.end(); ++asi) {
TextureStage *stage = (*asi)._stage;
if (a_stages.find(stage) != a_stages.end()) {
// This stage came from the original, and thus receives the
// original sort.
int implicit_sort = (*asi)._implicit_sort;
attrib->_on_stages.push_back(OnStageNode(stage, implicit_sort));
}
}
OnStages::const_iterator bsi;
for (bsi = ta->_on_stages.begin(); bsi != ta->_on_stages.end(); ++bsi) {
TextureStage *stage = (*bsi)._stage;
if (b_stages.find(stage) != b_stages.end()) {
// This stage was inherited from the secondary, and thus
// receives the secondary sort.
int implicit_sort = _next_implicit_sort + (*bsi)._implicit_sort;
attrib->_on_stages.push_back(OnStageNode(stage, implicit_sort));
}
}
attrib->_next_implicit_sort = _next_implicit_sort + ta->_next_implicit_sort;
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
@ -716,31 +816,27 @@ void TextureAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
#if 1
// TODO: write the multitexture data.
// write the boolean if _off_all_stages
// Write the off_stages information
dg.add_bool(_off_all_stages);
// write the number of off_stages
dg.add_uint16(get_num_off_stages());
// write the off stages pointers if any
OffStages::const_iterator fi;
for (fi = _off_stages.begin(); fi != _off_stages.end(); ++fi) {
TextureStage *stage = (*fi);
manager->write_pointer(dg, stage);
}
// write the number of on stages
// Write the on_stages information
dg.add_uint16(get_num_on_stages());
// write the on stages pointers if any
OnTextures::const_iterator nti;
for (nti = _on_textures.begin(); nti != _on_textures.end(); ++nti) {
TextureStage *stage = (*nti).first;
OnStages::const_iterator si;
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
TextureStage *stage = (*si)._stage;
Texture *tex = get_on_texture(stage);
nassertv(tex != (Texture *)NULL);
manager->write_pointer(dg, stage);
Texture *texture = (*nti).second;
manager->write_pointer(dg,texture);
manager->write_pointer(dg, tex);
dg.add_uint16((*si)._implicit_sort);
}
#else
manager->write_pointer(dg, get_texture());
#endif
}
////////////////////////////////////////////////////////////////////
@ -754,27 +850,27 @@ int TextureAttrib::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = RenderAttrib::complete_pointers(p_list, manager);
OffStages::iterator ci = _off_stages.begin();
while (ci != _off_stages.end()) {
OffStages::iterator ci;
for (ci = _off_stages.begin(); ci != _off_stages.end(); ++ci) {
TextureStage *ts = DCAST(TextureStage, p_list[pi++]);
*ci = ts;
++ci;
}
// read the pointers of the on_textures
_on_stages.reserve(_num_on_textures);
for (int i = 0; i < _num_on_textures; ++i) {
size_t sn = 0;
while (sn < _on_stages.size()) {
TextureStage *ts = DCAST(TextureStage, p_list[pi++]);
Texture *tx = DCAST(Texture, p_list[pi++]);
if (tx != (Texture *)NULL) {
_on_textures[ts] = tx;
_on_stages.push_back(ts);
Texture *tex = DCAST(Texture, p_list[pi++]);
if (tex != (Texture *)NULL) {
_on_textures[ts] = tex;
_on_stages[sn]._stage = ts;
++sn;
} else {
// If we couldn't load a texture pointer, turn off that
// particular texture stage.
_off_stages.push_back(ts);
_on_stages.erase(_on_stages.begin() + sn);
}
}
_sort_seq = UpdateSeq::old();
@ -813,9 +909,8 @@ void TextureAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
// read the boolean if _off_all_stages
// read the _off_stages data.
_off_all_stages = scan.get_bool();
// read the number of off_stages
int num_off_stages = scan.get_uint16();
// Push back a NULL pointer for each off TextureStage for now, until
@ -826,15 +921,26 @@ fillin(DatagramIterator &scan, BamReader *manager) {
manager->read_pointer(scan);
_off_stages.push_back(NULL);
}
// read the number of on stages
_num_on_textures = scan.get_uint16();
// just read the pointers, all allocation will happen from
// complete_pointers because it is a map template we get the actual
// list of pointers later in complete_pointers().
for (i = 0; i < _num_on_textures; i++) {
// Read the _on_stages data.
int num_on_stages = scan.get_uint16();
// Push back a NULL pointer for each off TextureStage and Texture
// for now, until we get the actual list of pointers later in
// complete_pointers().
_on_stages.reserve(num_on_stages);
_next_implicit_sort = 0;
for (i = 0; i < num_on_stages; i++) {
manager->read_pointer(scan);
manager->read_pointer(scan);
unsigned int implicit_sort;
if (manager->get_file_minor_ver() >= 15) {
implicit_sort = scan.get_uint16();
} else {
implicit_sort = (unsigned int)i;
}
_next_implicit_sort = max(_next_implicit_sort, implicit_sort + 1);
_on_stages.push_back(OnStageNode(NULL, implicit_sort));
}
}
@ -862,9 +968,9 @@ sort_on_stages() {
typedef pmap<const TextureStage *, int> TexcoordMap;
TexcoordMap tc_map;
OnStages::const_iterator osi;
for (osi = _on_stages.begin(); osi != _on_stages.end(); ++osi) {
TextureStage *stage = (*osi);
OnStages::const_iterator si;
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
TextureStage *stage = (*si)._stage;
if (stage->is_fixed_function()) {
const InternalName *name = stage->get_texcoord_name();
@ -880,17 +986,17 @@ sort_on_stages() {
}
// Now we can sort the on_stages map into render order.
sort(_on_stages.begin(), _on_stages.end(), IndirectLess<TextureStage>());
sort(_on_stages.begin(), _on_stages.end());
_sort_seq = TextureStage::get_sort_seq();
_on_ff_stages.clear();
_ff_tc_index.clear();
for (osi = _on_stages.begin(); osi != _on_stages.end(); ++osi) {
TextureStage *stage = (*osi);
for (si = _on_stages.begin(); si != _on_stages.end(); ++si) {
TextureStage *stage = (*si)._stage;
if (stage->is_fixed_function()) {
_on_ff_stages.push_back(stage);
_on_ff_stages.push_back(*si);
int texcoord_index = tc_map[stage];
_ff_tc_index.push_back(texcoord_index);
}

View File

@ -25,16 +25,14 @@
#include "texture.h"
#include "textureStage.h"
#include "updateSeq.h"
#include "indirectLess.h"
#include "geom.h"
#include "ordered_vector.h"
#include "vector_int.h"
////////////////////////////////////////////////////////////////////
// Class : TextureAttrib
// Description : Indicates which texture should be applied as the
// primary texture. Also see TextureAttrib2 for the
// secondary texture.
// Description : Indicates the set of TextureStages and their
// associated Textures that should be applied to (or
// removed from) a node.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_PGRAPH TextureAttrib : public RenderAttrib {
protected:
@ -81,8 +79,6 @@ PUBLISHED:
CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
public:
INLINE const Geom::ActiveTextureStages &get_on_stages() const;
INLINE const Geom::ActiveTextureStages &get_on_ff_stages() const;
CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;
virtual void output(ostream &out) const;
@ -102,10 +98,25 @@ private:
void sort_on_stages();
private:
typedef Geom::ActiveTextureStages OnStages;
class OnStageNode {
public:
INLINE OnStageNode(TextureStage *stage, unsigned int implicit_sort);
INLINE bool operator < (const OnStageNode &other) const;
PT(TextureStage) _stage;
unsigned int _implicit_sort;
};
class CompareTextureStagePriorities {
public:
bool operator () (const TextureAttrib::OnStageNode &a, const TextureAttrib::OnStageNode &b) const;
};
typedef pvector<OnStageNode> OnStages;
OnStages _on_stages;
OnStages _on_ff_stages;
vector_int _ff_tc_index;
unsigned int _next_implicit_sort;
typedef ov_set<TextureStage *> OffStages;
OffStages _off_stages;
@ -119,8 +130,6 @@ private:
UpdateSeq _sort_seq;
int _num_on_textures; //temporary count to complete_pointers from fill_in
static CPT(RenderAttrib) _empty_attrib;
static CPT(RenderAttrib) _all_off_attrib;

View File

@ -36,7 +36,7 @@ static const unsigned short _bam_major_ver = 6;
// Bumped to major version 5 on 5/6/05 for new Geom implementation.
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
static const unsigned short _bam_minor_ver = 14;
static const unsigned short _bam_minor_ver = 15;
// Bumped to minor version 1 on 3/12/06 to add Texture::_compression.
// Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask.
// Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images.
@ -51,6 +51,7 @@ static const unsigned short _bam_minor_ver = 14;
// Bumped to minor version 12 on 7/3/07 to rework control/frozen joints more.
// Bumped to minor version 13 on 8/15/07 to reverse CollisionPolygon vertices.
// Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
// Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
#endif