apply per-attrib override to TexMatrixAttrib also

This commit is contained in:
David Rose 2010-05-06 01:12:34 +00:00
parent 129f164f16
commit 91e6231a3c
8 changed files with 205 additions and 105 deletions

View File

@ -463,10 +463,12 @@ priv_step(double t) {
const RenderAttrib *attrib =
state->get_attrib(TexMatrixAttrib::get_class_type());
const TexMatrixAttrib *tma = NULL;
CPT(TexMatrixAttrib) tma;
if (attrib != (const TexMatrixAttrib *)NULL) {
tma = DCAST(TexMatrixAttrib, attrib);
transform = tma->get_transform(_texture_stage);
} else {
tma = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
}
if ((_flags & F_end_tex_offset) != 0) {
@ -512,11 +514,7 @@ priv_step(double t) {
}
// Apply the modified transform back to the state.
if (tma != (TexMatrixAttrib *)NULL) {
state = state->add_attrib(tma->add_stage(_texture_stage, transform), _override);
} else {
state = state->add_attrib(TexMatrixAttrib::make(_texture_stage, transform), _override);
}
state = state->set_attrib(tma->add_stage(_texture_stage, transform, _override));
}

View File

@ -20,7 +20,7 @@
// TexMatrixAttrib object.
////////////////////////////////////////////////////////////////////
INLINE TexMatrixAttrib::
TexMatrixAttrib() : _stage_list_stale(true) {
TexMatrixAttrib() {
}
////////////////////////////////////////////////////////////////////
@ -31,11 +31,27 @@ TexMatrixAttrib() : _stage_list_stale(true) {
////////////////////////////////////////////////////////////////////
INLINE TexMatrixAttrib::
TexMatrixAttrib(const TexMatrixAttrib &copy) :
_stages(copy._stages),
_stage_list_stale(true)
_stages(copy._stages)
{
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::get_override
// Access: Published
// Description: Returns the override value associated with the
// indicated stage.
////////////////////////////////////////////////////////////////////
INLINE int TexMatrixAttrib::
get_override(TextureStage *stage) const {
Stages::const_iterator si;
si = _stages.find(StageNode(stage));
if (si != _stages.end()) {
return (*si)._override;
}
nassert_raise("Specified TextureStage not included in attrib");
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::get_geom_rendering
// Access: Published
@ -56,14 +72,45 @@ get_geom_rendering(int geom_rendering) const {
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::check_stage_list
// Access: Private
// Description: Builds the linear list of TextureStages if it needs
// to be built.
// Function: TexMatrixAttrib::StageNode::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void TexMatrixAttrib::
check_stage_list() const {
if (_stage_list_stale) {
((TexMatrixAttrib *)this)->rebuild_stage_list();
}
INLINE TexMatrixAttrib::StageNode::
StageNode(const TextureStage *stage) :
// Yeah, we cast away the constness here. Just too much trouble to
// deal with it properly.
_stage((TextureStage *)stage),
_override(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::StageNode::operator <
// Access: Public
// Description: Compares the full attributes of StageNodes (as
// opposed to just the pointer compared by
// CompareTextureStagePointer, below).
////////////////////////////////////////////////////////////////////
INLINE bool TexMatrixAttrib::StageNode::
operator < (const TexMatrixAttrib::StageNode &other) const {
if (_stage != other._stage) {
return _stage < other._stage;
}
if (_transform != other._transform) {
return _transform < other._transform;
}
return _override < other._override;
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::CompareTextureStagePointer::operator ()
// Access: Public
// Description: This STL function object is used to sort a list of
// texture stages in order by pointer.
////////////////////////////////////////////////////////////////////
INLINE bool TexMatrixAttrib::CompareTextureStagePointer::
operator () (const TexMatrixAttrib::StageNode &a,
const TexMatrixAttrib::StageNode &b) const {
return a._stage < b._stage;
}

View File

@ -19,6 +19,7 @@
#include "bamWriter.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "textureStagePool.h"
CPT(RenderAttrib) TexMatrixAttrib::_empty_attrib;
TypeHandle TexMatrixAttrib::_type_handle;
@ -76,12 +77,7 @@ make(const LMatrix4f &mat) {
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) TexMatrixAttrib::
make(TextureStage *stage, const TransformState *transform) {
if (transform->is_identity()) {
return make();
}
TexMatrixAttrib *attrib = new TexMatrixAttrib;
attrib->_stages.insert(Stages::value_type(stage, transform));
return return_new(attrib);
return DCAST(TexMatrixAttrib, make())->add_stage(stage, transform);
}
////////////////////////////////////////////////////////////////////
@ -104,12 +100,13 @@ make_default() {
// this stage already exists, its transform is replaced.
////////////////////////////////////////////////////////////////////
CPT(RenderAttrib) TexMatrixAttrib::
add_stage(TextureStage *stage, const TransformState *transform) const {
if (transform->is_identity()) {
return remove_stage(stage);
}
add_stage(TextureStage *stage, const TransformState *transform,
int override) const {
TexMatrixAttrib *attrib = new TexMatrixAttrib(*this);
attrib->_stages[stage] = transform;
Stages::iterator si = attrib->_stages.insert(StageNode(stage)).first;
(*si)._transform = transform;
(*si)._override = override;
return return_new(attrib);
}
@ -122,7 +119,7 @@ add_stage(TextureStage *stage, const TransformState *transform) const {
CPT(RenderAttrib) TexMatrixAttrib::
remove_stage(TextureStage *stage) const {
TexMatrixAttrib *attrib = new TexMatrixAttrib(*this);
attrib->_stages.erase(stage);
attrib->_stages.erase(StageNode(stage));
return return_new(attrib);
}
@ -158,7 +155,7 @@ is_empty() const {
////////////////////////////////////////////////////////////////////
bool TexMatrixAttrib::
has_stage(TextureStage *stage) const {
Stages::const_iterator mi = _stages.find(stage);
Stages::const_iterator mi = _stages.find(StageNode(stage));
return (mi != _stages.end());
}
@ -183,38 +180,33 @@ get_num_stages() const {
TextureStage *TexMatrixAttrib::
get_stage(int n) const {
nassertr(n >= 0 && n < (int)_stages.size(), NULL);
check_stage_list();
return _stage_list[n];
return _stages[n]._stage;
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::get_mat
// Access: Published
// Description: Returns the transformation matrix associated with
// the named texture stage, or identity matrix if
// the indicated texture stage, or identity matrix if
// nothing is associated with the indicated stage.
////////////////////////////////////////////////////////////////////
const LMatrix4f &TexMatrixAttrib::
get_mat(TextureStage *stage) const {
Stages::const_iterator mi = _stages.find(stage);
if (mi != _stages.end()) {
return (*mi).second->get_mat();
}
return LMatrix4f::ident_mat();
return get_transform(stage)->get_mat();
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::get_transform
// Access: Published
// Description: Returns the transformation associated with
// the named texture stage, or identity matrix if
// the indicated texture stage, or identity matrix if
// nothing is associated with the indicated stage.
////////////////////////////////////////////////////////////////////
CPT(TransformState) TexMatrixAttrib::
get_transform(TextureStage *stage) const {
Stages::const_iterator mi = _stages.find(stage);
Stages::const_iterator mi = _stages.find(StageNode(stage));
if (mi != _stages.end()) {
return (*mi).second;
return (*mi)._transform;
}
return TransformState::make_identity();
}
@ -230,9 +222,11 @@ output(ostream &out) const {
Stages::const_iterator mi;
for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
TextureStage *stage = (*mi).first;
const TransformState *transform = (*mi).second;
out << " " << stage->get_name() << "(" << *transform << ")";
const StageNode &sn = (*mi);
out << " " << sn._stage->get_name() << "(" << *sn._transform << ")";
if (sn._override != 0) {
out << "^" << sn._override;
}
}
}
@ -260,19 +254,16 @@ compare_to_impl(const RenderAttrib *other) const {
ai = _stages.begin();
bi = ta->_stages.begin();
while (ai != _stages.end() && bi != ta->_stages.end()) {
if ((*ai).first < (*bi).first) {
if ((*ai) < (*bi)) {
// This stage is in a but not in b.
return -1;
} else if ((*bi).first < (*ai).first) {
} else if ((*bi) < (*ai)) {
// This stage is in b but not in a.
return 1;
} else {
// This stage is in both; compare the stages.
if ((*ai).second != (*bi).second) {
return (*ai).second < (*bi).second ? -1 : 1;
}
// This stage is in both.
++ai;
++bi;
}
@ -322,20 +313,33 @@ compose_impl(const RenderAttrib *other) const {
ai = _stages.begin();
bi = ta->_stages.begin();
while (ai != _stages.end() && bi != ta->_stages.end()) {
if ((*ai).first < (*bi).first) {
if ((*ai)._stage < (*bi)._stage) {
// This stage is in a but not in b.
attrib->_stages.insert(attrib->_stages.end(), *ai);
++ai;
} else if ((*bi).first < (*ai).first) {
} else if ((*bi)._stage < (*ai)._stage) {
// This stage is in b but not in a.
attrib->_stages.insert(attrib->_stages.end(), *bi);
++bi;
} else {
// This stage is in both; compose the stages.
CPT(TransformState) new_transform = (*ai).second->compose((*bi).second);
attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, new_transform));
// This stage is in both.
if ((*ai)._override == (*bi)._override) {
// Same override; compose them.
CPT(TransformState) new_transform = (*ai)._transform->compose((*bi)._transform);
StageNode sn((*ai)._stage);
sn._transform = new_transform;
sn._override = (*ai)._override;
attrib->_stages.insert(attrib->_stages.end(), sn);
} else if ((*ai)._override < (*bi)._override) {
// Override b wins.
attrib->_stages.insert(attrib->_stages.end(), *bi);
} else {
// Override a wins.
attrib->_stages.insert(attrib->_stages.end(), *ai);
}
++ai;
++bi;
}
@ -379,23 +383,45 @@ invert_compose_impl(const RenderAttrib *other) const {
ai = _stages.begin();
bi = ta->_stages.begin();
while (ai != _stages.end() && bi != ta->_stages.end()) {
if ((*ai).first < (*bi).first) {
if ((*ai)._stage < (*bi)._stage) {
// This stage is in a but not in b.
CPT(TransformState) inv_a =
(*ai).second->invert_compose(TransformState::make_identity());
attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, inv_a));
(*ai)._transform->invert_compose(TransformState::make_identity());
StageNode sn((*ai)._stage);
sn._transform = inv_a;
sn._override = (*ai)._override;
attrib->_stages.insert(attrib->_stages.end(), sn);
++ai;
} else if ((*bi).first < (*ai).first) {
} else if ((*bi)._stage < (*ai)._stage) {
// This stage is in b but not in a.
attrib->_stages.insert(attrib->_stages.end(), *bi);
++bi;
} else {
// This stage is in both; compose the stages.
CPT(TransformState) new_transform =
(*ai).second->invert_compose((*bi).second);
attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, new_transform));
// This stage is in both.
if ((*ai)._override == (*bi)._override) {
// Same override; compose them.
CPT(TransformState) new_transform = (*ai)._transform->invert_compose((*bi)._transform);
StageNode sn((*ai)._stage);
sn._transform = new_transform;
sn._override = (*ai)._override;
attrib->_stages.insert(attrib->_stages.end(), sn);
} else if ((*ai)._override < (*bi)._override) {
// Override b wins.
attrib->_stages.insert(attrib->_stages.end(), *bi);
} else {
// Override a wins.
CPT(TransformState) inv_a =
(*ai)._transform->invert_compose(TransformState::make_identity());
StageNode sn((*ai)._stage);
sn._transform = inv_a;
sn._override = (*ai)._override;
attrib->_stages.insert(attrib->_stages.end(), sn);
}
++ai;
++bi;
}
@ -404,8 +430,11 @@ invert_compose_impl(const RenderAttrib *other) const {
while (ai != _stages.end()) {
// This stage is in a but not in b.
CPT(TransformState) inv_a =
(*ai).second->invert_compose(TransformState::make_identity());
attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, inv_a));
(*ai)._transform->invert_compose(TransformState::make_identity());
StageNode sn((*ai)._stage);
sn._transform = inv_a;
sn._override = (*ai)._override;
attrib->_stages.insert(attrib->_stages.end(), sn);
++ai;
}
@ -418,25 +447,6 @@ invert_compose_impl(const RenderAttrib *other) const {
return return_new(attrib);
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::rebuild_stage_list
// Access: Private
// Description: Builds the linear list of TextureStages, the first
// time someone asks for it.
////////////////////////////////////////////////////////////////////
void TexMatrixAttrib::
rebuild_stage_list() {
_stage_list.clear();
_stage_list.reserve(_stages.size());
Stages::const_iterator si;
for (si = _stages.begin(); si != _stages.end(); ++si) {
_stage_list.push_back((*si).first);
}
_stage_list_stale = false;
}
////////////////////////////////////////////////////////////////////
// Function: TexMatrixAttrib::register_with_read_factory
// Access: Public, Static
@ -462,11 +472,11 @@ write_datagram(BamWriter *manager, Datagram &dg) {
Stages::const_iterator si;
for (si = _stages.begin(); si != _stages.end(); ++si) {
TextureStage *stage = (*si).first;
const TransformState *transform = (*si).second;
const StageNode &sn = (*si);
manager->write_pointer(dg, stage);
manager->write_pointer(dg, transform);
manager->write_pointer(dg, sn._stage);
manager->write_pointer(dg, sn._transform);
dg.add_int32(sn._override);
}
}
@ -481,11 +491,18 @@ int TexMatrixAttrib::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = RenderAttrib::complete_pointers(p_list, manager);
for (size_t i = 0; i < _num_stages; i++) {
TextureStage *stage = DCAST(TextureStage, p_list[pi++]);
for (size_t sni = 0; sni < _stages.size(); ++sni) {
// Filter the TextureStage through the TextureStagePool.
PT(TextureStage) ts = DCAST(TextureStage, p_list[pi++]);
ts = TextureStagePool::get_stage(ts);
const TransformState *transform = DCAST(TransformState, p_list[pi++]);
_stages[stage] = transform;
StageNode &sn = _stages[sni];
sn._stage = ts;
sn._transform = transform;
}
_stages.sort();
return pi;
}
@ -521,9 +538,17 @@ void TexMatrixAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_num_stages = scan.get_uint16();
for (size_t i = 0; i < _num_stages; i++) {
size_t num_stages = scan.get_uint16();
for (size_t i = 0; i < num_stages; i++) {
manager->read_pointer(scan);
manager->read_pointer(scan);
int override = 0;
if (manager->get_file_minor_ver() >= 24) {
override = scan.get_int32();
}
StageNode sn(NULL);
sn._override = override;
_stages.push_back(sn);
}
}

View File

@ -44,7 +44,7 @@ PUBLISHED:
static CPT(RenderAttrib) make(TextureStage *stage, const TransformState *transform);
static CPT(RenderAttrib) make_default();
CPT(RenderAttrib) add_stage(TextureStage *stage, const TransformState *transform) const;
CPT(RenderAttrib) add_stage(TextureStage *stage, const TransformState *transform, int override = 0) const;
CPT(RenderAttrib) remove_stage(TextureStage *stage) const;
bool is_empty() const;
@ -58,6 +58,7 @@ PUBLISHED:
const LMatrix4f &get_mat(TextureStage *stage) const;
CPT(TransformState) get_transform(TextureStage *stage) const;
INLINE int get_override(TextureStage *stage) const;
INLINE int get_geom_rendering(int geom_rendering) const;
@ -73,17 +74,26 @@ private:
INLINE void check_stage_list() const;
void rebuild_stage_list();
typedef pmap< PT(TextureStage), CPT(TransformState) > Stages;
private:
class StageNode {
public:
INLINE StageNode(const TextureStage *stage);
INLINE bool operator < (const StageNode &other) const;
PT(TextureStage) _stage;
CPT(TransformState) _transform;
int _override;
};
class CompareTextureStagePointer {
public:
INLINE bool operator () (const TexMatrixAttrib::StageNode &a, const TexMatrixAttrib::StageNode &b) const;
};
typedef ov_set<StageNode, CompareTextureStagePointer> Stages;
Stages _stages;
typedef pvector<TextureStage *> StageList;
StageList _stage_list;
bool _stage_list_stale;
// This element is only used during reading from a bam file. It has
// no meaningful value any other time.
size_t _num_stages;
static CPT(RenderAttrib) _empty_attrib;
PUBLISHED:

View File

@ -175,6 +175,23 @@ get_on_texture(TextureStage *stage) const {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::get_on_stage_override
// Access: Published
// Description: Returns the override value associated with the
// indicated stage.
////////////////////////////////////////////////////////////////////
INLINE int TextureAttrib::
get_on_stage_override(TextureStage *stage) const {
Stages::const_iterator si;
si = _on_stages.find(StageNode(stage));
if (si != _on_stages.end()) {
return (*si)._override;
}
nassert_raise("Specified TextureStage not included in attrib");
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::get_num_off_stages
// Access: Published

View File

@ -773,6 +773,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
_on_stages.erase(_on_stages.begin() + sni);
}
}
_on_stages.sort();
_sort_seq = UpdateSeq::old();
_filtered_seq = UpdateSeq::old();

View File

@ -61,6 +61,7 @@ PUBLISHED:
INLINE int get_ff_tc_index(int n) const;
INLINE bool has_on_stage(TextureStage *stage) const;
INLINE Texture *get_on_texture(TextureStage *stage) const;
INLINE int get_on_stage_override(TextureStage *stage) const;
int find_on_stage(const TextureStage *stage) const;

View File

@ -33,7 +33,7 @@ static const unsigned short _bam_major_ver = 6;
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
static const unsigned short _bam_first_minor_ver = 14;
static const unsigned short _bam_minor_ver = 23;
static const unsigned short _bam_minor_ver = 24;
// 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.
// Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level.
@ -44,6 +44,7 @@ static const unsigned short _bam_minor_ver = 23;
// Bumped to minor version 21 on 2/26/08 to add BamEnums::BamObjectCode.
// Bumped to minor version 22 on 7/31/09 to add UvScrollNode R speed.
// Bumped to minor version 23 on 5/4/10 to add internal TextureAttrib overrides.
// Bumped to minor version 24 on 5/4/10 to add internal TexMatrixAttrib overrides.
#endif