TextureAttrib::_implicit_sort
This commit is contained in:
parent
61b849ee15
commit
a667e91dce
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -158,10 +158,6 @@ public:
|
|||
|
||||
static UpdateSeq get_next_modified();
|
||||
|
||||
public:
|
||||
typedef pvector< PT(TextureStage) > ActiveTextureStages;
|
||||
typedef pset<TextureStage *> NoTexCoordStages;
|
||||
|
||||
private:
|
||||
class CData;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 ©) :
|
||||
_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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue