15 #include "renderEffects.h"
16 #include "billboardEffect.h"
17 #include "decalEffect.h"
18 #include "compassEffect.h"
19 #include "polylightEffect.h"
20 #include "showBoundsEffect.h"
21 #include "config_pgraph.h"
22 #include "bamReader.h"
23 #include "bamWriter.h"
24 #include "datagramIterator.h"
26 #include "compareTo.h"
27 #include "lightReMutexHolder.h"
28 #include "lightMutexHolder.h"
47 if (_states == (States *)NULL) {
50 _saved_entry = _states->end();
60 RenderEffects(
const RenderEffects &) {
70 operator = (
const RenderEffects &) {
86 nassertv(_saved_entry == _states->end());
98 Effects::const_iterator ai;
99 for (ai = _effects.
begin(); ai != _effects.
end(); ++ai) {
100 const Effect &effect = (*ai);
101 if (!effect._effect->safe_to_transform()) {
117 CPT(TransformState) RenderEffects::
118 prepare_flatten_transform(const TransformState *net_transform)
const {
119 CPT(TransformState) result = net_transform;
120 Effects::const_iterator ai;
121 for (ai = _effects.begin(); ai != _effects.end(); ++ai) {
122 const Effect &effect = (*ai);
123 result = effect._effect->prepare_flatten_transform(result);
139 Effects::const_iterator ai;
140 for (ai = _effects.
begin(); ai != _effects.
end(); ++ai) {
141 const Effect &effect = (*ai);
142 if (!effect._effect->safe_to_combine()) {
156 CPT(RenderEffects) RenderEffects::
162 RenderEffects *new_state =
new RenderEffects;
163 back_insert_iterator<Effects> result =
164 back_inserter(new_state->_effects);
166 Effects::const_iterator ai;
167 for (ai = _effects.begin(); ai != _effects.end(); ++ai) {
168 const Effect &effect = (*ai);
169 Effect new_effect(effect);
170 new_effect._effect = effect._effect->xform(mat);
171 *result = new_effect;
175 return return_new(new_state);
194 return lexicographical_compare(_effects.
begin(), _effects.
end(),
195 other._effects.
begin(), other._effects.
end(),
209 Effects::const_iterator ai = _effects.find(Effect(type));
210 if (ai == _effects.
end()) {
213 return ai - _effects.
begin();
221 CPT(RenderEffects) RenderEffects::
225 if (_empty_state == (RenderEffects *)NULL) {
226 RenderEffects *state =
new RenderEffects;
227 _empty_state = return_new(state);
238 CPT(RenderEffects) RenderEffects::
240 RenderEffects *state =
new RenderEffects;
242 state->_effects.insert(Effect(effect));
243 return return_new(state);
251 CPT(RenderEffects) RenderEffects::
254 RenderEffects *state =
new RenderEffects;
256 state->_effects.
push_back(Effect(effect1));
257 state->_effects.
push_back(Effect(effect2));
258 state->_effects.
sort();
259 return return_new(state);
267 CPT(RenderEffects) RenderEffects::
271 RenderEffects *state =
new RenderEffects;
273 state->_effects.
push_back(Effect(effect1));
274 state->_effects.
push_back(Effect(effect2));
275 state->_effects.
push_back(Effect(effect3));
276 state->_effects.
sort();
277 return return_new(state);
285 CPT(RenderEffects) RenderEffects::
290 RenderEffects *state =
new RenderEffects;
292 state->_effects.
push_back(Effect(effect1));
293 state->_effects.
push_back(Effect(effect2));
294 state->_effects.
push_back(Effect(effect3));
295 state->_effects.
push_back(Effect(effect4));
296 state->_effects.
sort();
297 return return_new(state);
308 CPT(RenderEffects) RenderEffects::
310 RenderEffects *new_state =
new RenderEffects;
311 back_insert_iterator<Effects> result =
312 back_inserter(new_state->_effects);
314 Effect new_effect(effect);
315 Effects::const_iterator ai = _effects.begin();
317 while (ai != _effects.end() && (*ai) < new_effect) {
322 *result = new_effect;
325 if (ai != _effects.end() && !(new_effect < (*ai))) {
333 while (ai != _effects.end()) {
339 return return_new(new_state);
349 CPT(RenderEffects) RenderEffects::
351 RenderEffects *new_state =
new RenderEffects;
352 back_insert_iterator<Effects> result =
353 back_inserter(new_state->_effects);
355 Effects::const_iterator ai = _effects.begin();
357 while (ai != _effects.end()) {
358 if ((*ai)._type != type) {
365 return return_new(new_state);
377 Effects::const_iterator ai;
378 ai = _effects.find(Effect(type));
379 if (ai != _effects.
end()) {
380 return (*ai)._effect;
414 ((RenderEffects *)
this)->release_new();
425 output(ostream &out)
const {
427 if (_effects.
empty()) {
431 Effects::const_iterator ai = _effects.
begin();
432 out <<
"(" << (*ai)._type;
434 while (ai != _effects.
end()) {
435 out <<
" " << (*ai)._type;
448 write(ostream &out,
int indent_level)
const {
449 indent(out, indent_level) << _effects.
size() <<
" effects:\n";
450 Effects::const_iterator ai;
451 for (ai = _effects.
begin(); ai != _effects.
end(); ++ai) {
452 const Effect &effect = (*ai);
453 effect._effect->write(out, indent_level + 2);
466 if (_states == (
States *)NULL) {
470 return _states->size();
482 out << _states->size() <<
" states:\n";
483 States::const_iterator si;
484 for (si = _states->begin(); si != _states->end(); ++si) {
485 const RenderEffects *state = (*si);
486 state->write(out, 2);
500 if (_states->empty()) {
505 States::const_iterator si = _states->begin();
506 States::const_iterator snext = si;
508 while (snext != _states->end()) {
509 if (!(*(*si) < *(*snext))) {
511 <<
"RenderEffects out of order!\n";
512 (*si)->write(pgraph_cat.error(
false), 2);
513 (*snext)->write(pgraph_cat.error(
false), 2);
516 if ((*(*snext) < *(*si))) {
518 <<
"RenderEffects::operator < not defined properly!\n";
519 pgraph_cat.error(
false)
520 <<
"a < b: " << (*(*si) < *(*snext)) <<
"\n";
521 pgraph_cat.error(
false)
522 <<
"b < a: " << (*(*snext) < *(*si)) <<
"\n";
523 (*si)->write(pgraph_cat.error(
false), 2);
524 (*snext)->write(pgraph_cat.error(
false), 2);
543 CPT(TransformState) &node_transform,
545 Effects::const_iterator ei;
546 for (ei = _effects.
begin(); ei != _effects.
end(); ++ei) {
547 (*ei)._effect->cull_callback(trav, data, node_transform, node_state);
565 CPT(TransformState) &node_transform,
567 Effects::const_iterator ei;
568 for (ei = _effects.
begin(); ei != _effects.
end(); ++ei) {
569 (*ei)._effect->adjust_transform(net_transform, node_transform, node);
592 _states_lock =
new LightReMutex(
"RenderEffects::_states_lock");
609 CPT(RenderEffects) RenderEffects::
610 return_new(RenderEffects *state) {
611 nassertr(state != (RenderEffects *)NULL, state);
620 if (paranoid_const) {
621 nassertr(validate_states(), state);
629 nassertr(state->_saved_entry == _states->end(), state);
633 CPT(RenderEffects) pt_state = state;
635 pair<States::iterator,
bool> result = _states->insert(state);
639 state->_saved_entry = result.first;
640 nassertr(_states->find(state) == state->_saved_entry, pt_state);
646 return *(result.first);
662 if (_saved_entry != _states->end()) {
663 nassertv(_states->find(
this) == _saved_entry);
664 _states->erase(_saved_entry);
665 _saved_entry = _states->end();
677 if ((_flags & F_checked_decal) != 0) {
684 _flags |= F_has_decal;
686 _flags |= F_checked_decal;
695 determine_show_bounds() {
697 if ((_flags & F_checked_show_bounds) != 0) {
704 _flags |= F_has_show_bounds;
707 _flags |= F_has_show_tight_bounds;
710 _flags |= F_checked_show_bounds;
719 determine_cull_callback() {
721 if ((_flags & F_checked_cull_callback) != 0) {
726 _flags |= F_checked_cull_callback;
728 Effects::const_iterator ei;
729 for (ei = _effects.
begin(); ei != _effects.
end(); ++ei) {
730 if ((*ei)._effect->has_cull_callback()) {
731 _flags |= F_has_cull_callback;
743 determine_adjust_transform() {
745 if ((_flags & F_checked_adjust_transform) != 0) {
750 _flags |= F_checked_adjust_transform;
752 Effects::const_iterator ei;
753 for (ei = _effects.
begin(); ei != _effects.
end(); ++ei) {
754 if ((*ei)._effect->has_adjust_transform()) {
755 _flags |= F_has_adjust_transform;
782 int num_effects = _effects.
size();
783 nassertv(num_effects == (
int)(PN_uint16)num_effects);
786 Effects::const_iterator ai;
787 for (ai = _effects.
begin(); ai != _effects.
end(); ++ai) {
788 const Effect &effect = (*ai);
807 while (i < _effects.
size()) {
808 Effect &effect = _effects[i];
814 _effects.erase(_effects.
begin() + i);
818 effect._type = effect._effect->get_type();
829 nassertr(_saved_entry == _states->end(), pi);
869 RenderEffects *state = DCAST(RenderEffects, old_ptr);
870 CPT(RenderEffects) pointer = return_new(state);
877 if (pointer == state) {
884 return (RenderEffects *)pointer.p();
917 RenderEffects *state =
new RenderEffects;
921 parse_params(params, scan, manager);
922 state->fillin(scan, manager);
944 for (
int i = 0; i < num_effects; i++) {
949 nassertv(_saved_entry == _states->end());
static void list_states(ostream &out)
Lists all of the RenderEffects in the cache to the output stream, one per line.
A basic node of the scene graph or data graph.
An STL function object class, this is intended to be used on any ordered collection of classes that c...
virtual bool unref() const
This method overrides ReferenceCount::unref() to check whether the remaining reference count is entir...
int find_effect(TypeHandle type) const
Searches for an effect with the indicated type in the state, and returns its index if it is found...
static TypedWritable * change_this(TypedWritable *old_ptr, BamReader *manager)
Called immediately after complete_pointers(), this gives the object a chance to adjust its own pointe...
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
bool debug_is_locked() const
Returns true if the current thread has locked the LightReMutex, false otherwise.
static void init_states()
Make sure the global _states map is allocated.
Base class for objects that can be written to and read from Bam files.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
A lightweight reentrant mutex.
bool get_tight() const
Returns true if the "tight" flag was set, meaning the effect should compute and draw the tight boun...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
virtual bool require_fully_complete() const
Some objects require all of their nested pointers to have been completed before the objects themselve...
Applied to a GeomNode to cause a visible bounding volume to be drawn for this node.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
This is the base class for a number of special render effects that may be set on scene graph nodes to...
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
bool safe_to_combine() const
Returns true if all of the effects in this set can safely be shared with a sibling node that has the ...
void reserve(size_type_0 n)
Informs the vector of a planned change in size; ensures that the capacity of the vector is greater th...
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
void register_change_this(ChangeThisFunc func, TypedWritable *whom)
Called by an object reading itself from the bam file to indicate that the object pointer that will be...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
static bool validate_states()
Ensures that the cache is still stored in sorted order.
static Thread * get_main_thread()
Returns a pointer to the "main" Thread object–this is the Thread that started the whole process...
const RenderEffect * get_effect(int n) const
Returns the nth effect in the state.
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
void cull_callback(CullTraverser *trav, CullTraverserData &data, CPT(TransformState)&node_transform, CPT(RenderState)&node_state) const
Calls cull_callback() on all effects.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
virtual bool unref() const
Explicitly decrements the reference count.
This is a 4-by-4 transform matrix.
Similar to MutexHolder, but for a light mutex.
bool safe_to_transform() const
Returns true if all of the effects in this set can safely be transformed, and therefore the complete ...
void sort()
Maps to sort_unique().
An instance of this class is passed to the Factory when requesting it to do its business and construc...
static void register_with_read_factory()
Tells the BamReader how to create objects of type RenderEffects.
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
Similar to MutexHolder, but for a light reentrant mutex.
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
bool operator<(const RenderEffects &other) const
Provides an arbitrary ordering among all unique RenderEffects, so we can store the essentially differ...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
static int get_num_states()
Returns the total number of unique RenderEffects objects allocated in the world.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
void adjust_transform(CPT(TransformState)&net_transform, CPT(TransformState)&node_transform, PandaNode *node) const
Calls adjust_transform() on all effects.
size_type_0 size() const
Returns the number of elements in the ordered vector.
This is our own Panda specialization on the default STL set.
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
int get_ref_count() const
Returns the current reference count.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
virtual ~RenderEffects()
The destructor is responsible for removing the RenderEffects from the global set if it is there...
This represents a unique collection of RenderEffect objects that correspond to a particular renderabl...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.