Panda3D
texProjectorEffect.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file texProjectorEffect.cxx
10  * @author drose
11  * @date 2004-07-25
12  */
13 
14 #include "texProjectorEffect.h"
15 #include "cullTraverserData.h"
16 #include "texMatrixAttrib.h"
17 #include "lensNode.h"
18 #include "config_pgraph.h"
19 #include "nodePath.h"
20 #include "bamReader.h"
21 #include "bamWriter.h"
22 #include "datagram.h"
23 #include "datagramIterator.h"
24 
25 CPT(RenderEffect) TexProjectorEffect::_empty_effect;
26 TypeHandle TexProjectorEffect::_type_handle;
27 
28 /**
29  *
30  */
31 TexProjectorEffect::
32 ~TexProjectorEffect() {
33 }
34 
35 /**
36  * Constructs a TexProjectorEffect that modifies no stages at all.
37  */
38 CPT(RenderEffect) TexProjectorEffect::
39 make() {
40  // We make it a special case and store a pointer to the empty effect forever
41  // once we find it the first time, as an optimization.
42  if (_empty_effect == nullptr) {
43  _empty_effect = return_new(new TexProjectorEffect);
44  }
45 
46  return _empty_effect;
47 }
48 
49 /**
50  * Returns a new TexProjectorEffect just like this one, with the indicated
51  * projection for the given stage. If this stage already exists, its
52  * projection definition is replaced.
53  *
54  * The relative transform between the "from" and the "to" nodes is
55  * automatically applied to the texture transform each frame.
56  *
57  * Furthermore, if the "to" node is a LensNode, its projection matrix is also
58  * applied to the texture transform. In this case, the lens_index may be used
59  * to select the particular lens that should be used.
60  */
61 CPT(RenderEffect) TexProjectorEffect::
62 add_stage(TextureStage *stage, const NodePath &from, const NodePath &to, int lens_index) const {
63  TexProjectorEffect *effect = new TexProjectorEffect(*this);
64  StageDef &def = effect->_stages[stage];
65  def.set_from(from);
66  def.set_to(to);
67  def.set_lens_index(lens_index);
68  return return_new(effect);
69 }
70 
71 /**
72  * Returns a new TexProjectorEffect just like this one, with the indicated
73  * stage removed.
74  */
75 CPT(RenderEffect) TexProjectorEffect::
76 remove_stage(TextureStage *stage) const {
77  TexProjectorEffect *effect = new TexProjectorEffect(*this);
78  effect->_stages.erase(stage);
79  return return_new(effect);
80 }
81 
82 /**
83  * Returns true if no stages are defined in the TexProjectorEffect, false if
84  * at least one is.
85  */
86 bool TexProjectorEffect::
87 is_empty() const {
88  return _stages.empty();
89 }
90 
91 /**
92  * Returns true if there is a transform associated with the indicated stage,
93  * or false otherwise (in which case get_transform(stage) will return the
94  * identity transform).
95  */
96 bool TexProjectorEffect::
97 has_stage(TextureStage *stage) const {
98  Stages::const_iterator mi = _stages.find(stage);
99  return (mi != _stages.end());
100 }
101 
102 /**
103  * Returns the "from" node associated with the TexProjectorEffect on the
104  * indicated stage. The relative transform between the "from" and the "to"
105  * nodes is automatically applied to the texture transform each frame.
106  */
107 NodePath TexProjectorEffect::
108 get_from(TextureStage *stage) const {
109  Stages::const_iterator mi = _stages.find(stage);
110  nassertr(mi != _stages.end(), NodePath::fail());
111  return (*mi).second._from;
112 }
113 
114 /**
115  * Returns the "to" node associated with the TexProjectorEffect on the
116  * indicated stage. The relative transform between the "from" and the "to"
117  * nodes is automatically applied to the texture transform each frame.
118  *
119  * Furthermore, if the "to" node is a LensNode, its projection matrix is also
120  * applied to the texture transform.
121  */
122 NodePath TexProjectorEffect::
123 get_to(TextureStage *stage) const {
124  Stages::const_iterator mi = _stages.find(stage);
125  nassertr(mi != _stages.end(), NodePath::fail());
126  return (*mi).second._to;
127 }
128 
129 /**
130  * Returns the lens_index associated with the TexProjectorEffect on the
131  * indicated stage. This is only used if the "to" node is a LensNode, in
132  * which case it specifies the particular lens that should be used.
133  */
134 int TexProjectorEffect::
135 get_lens_index(TextureStage *stage) const {
136  Stages::const_iterator mi = _stages.find(stage);
137  nassertr(mi != _stages.end(), 0);
138  return (*mi).second._lens_index;
139 }
140 
141 /**
142  *
143  */
144 void TexProjectorEffect::
145 output(std::ostream &out) const {
146  out << get_type() << ":";
147 
148  Stages::const_iterator mi;
149  for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
150  TextureStage *stage = (*mi).first;
151  const StageDef &def = (*mi).second;
152  out << " " << stage->get_name() << "(" << def._to
153  << ", " << def._from << ", " << def._lens_index << ")";
154  }
155 }
156 
157 /**
158  * Should be overridden by derived classes to return true if cull_callback()
159  * has been defined. Otherwise, returns false to indicate cull_callback()
160  * does not need to be called for this effect during the cull traversal.
161  */
162 bool TexProjectorEffect::
163 has_cull_callback() const {
164  return !_stages.empty();
165 }
166 
167 /**
168  * If has_cull_callback() returns true, this function will be called during
169  * the cull traversal to perform any additional operations that should be
170  * performed at cull time. This may include additional manipulation of render
171  * state or additional visible/invisible decisions, or any other arbitrary
172  * operation.
173  *
174  * At the time this function is called, the current node's transform and state
175  * have not yet been applied to the net_transform and net_state. This
176  * callback may modify the node_transform and node_state to apply an effective
177  * change to the render state at this level.
178  */
179 void TexProjectorEffect::
180 cull_callback(CullTraverser *trav, CullTraverserData &data,
181  CPT(TransformState) &node_transform,
182  CPT(RenderState) &node_state) const {
183  CPT(TexMatrixAttrib) tex_matrix = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
184 
185  Stages::const_iterator mi;
186  for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
187  TextureStage *stage = (*mi).first;
188  const StageDef &def = (*mi).second;
189 
190  CPT(TransformState) transform = def._from.get_transform(def._to);
191 
192  if (def._to_lens_node != nullptr &&
193  def._to_lens_node->get_lens() != nullptr) {
194 
195  // Get the lens's projection matrix, as a TransformState.
196  Lens *lens = def._to_lens_node->get_lens(def._lens_index);
197  if (lens != nullptr) {
198  CPT(TransformState) projmat = TransformState::make_mat(lens->get_projection_mat());
199 
200  // We need a special transform to convert the -0.5, 0.5 centering of
201  // the lens's projection matrix to UV's in the range of (0, 1).
202  static CPT(TransformState) fixmat;
203  if (fixmat == nullptr) {
204  fixmat = TransformState::make_pos_hpr_scale
205  (LVecBase3(0.5f, 0.5f, 0.0f),
206  LVecBase3(0.0f, 0.0f, 0.0f),
207  LVecBase3(0.5f, 0.5f, 1.0f));
208  }
209 
210  // Now apply both to the current transform.
211  transform = fixmat->compose(projmat)->compose(transform);
212  }
213  }
214 
215  if (!transform->is_identity()) {
216  tex_matrix = DCAST(TexMatrixAttrib,
217  tex_matrix->add_stage(stage, transform));
218  }
219  }
220 
221  if (!tex_matrix->is_empty()) {
222  node_state = node_state->compose(RenderState::make(tex_matrix));
223  }
224 }
225 
226 /**
227  * Intended to be overridden by derived TexProjectorEffect types to return a
228  * unique number indicating whether this TexProjectorEffect is equivalent to
229  * the other one.
230  *
231  * This should return 0 if the two TexProjectorEffect objects are equivalent,
232  * a number less than zero if this one should be sorted before the other one,
233  * and a number greater than zero otherwise.
234  *
235  * This will only be called with two TexProjectorEffect objects whose
236  * get_type() functions return the same.
237  */
238 int TexProjectorEffect::
239 compare_to_impl(const RenderEffect *other) const {
240  const TexProjectorEffect *ta;
241  DCAST_INTO_R(ta, other, 0);
242 
243  Stages::const_iterator ai, bi;
244  ai = _stages.begin();
245  bi = ta->_stages.begin();
246  while (ai != _stages.end() && bi != ta->_stages.end()) {
247  if ((*ai).first < (*bi).first) {
248  // This stage is in a but not in b.
249  return -1;
250 
251  } else if ((*bi).first < (*ai).first) {
252  // This stage is in b but not in a.
253  return 1;
254 
255  } else {
256  // This stage is in both; compare the stages.
257  int compare = (*ai).second.compare_to((*bi).second);
258  if (compare != 0) {
259  return compare;
260  }
261  ++ai;
262  ++bi;
263  }
264  }
265 
266  if (bi != ta->_stages.end()) {
267  // a ran out first; b was longer.
268  return -1;
269  }
270 
271  if (ai != _stages.end()) {
272  // b ran out first; a was longer.
273  return 1;
274  }
275 
276  return 0;
277 }
278 
279 /**
280  * Tells the BamReader how to create objects of type TexProjectorEffect.
281  */
282 void TexProjectorEffect::
283 register_with_read_factory() {
284  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
285 }
286 
287 /**
288  * Writes the contents of this object to the datagram for shipping out to a
289  * Bam file.
290  */
292 write_datagram(BamWriter *manager, Datagram &dg) {
293  RenderEffect::write_datagram(manager, dg);
294 
295  // For now, we don't write anything to the bam file for a
296  // TexProjectorEffect, except a bogus 0 "size" which may one day indicate
297  // the number of stages in the map that we might write out.
298  dg.add_uint16(0);
299 
300  // One day we will write the whole map out. We don't do this yet, because
301  // (a) we don't have an interface for writing out NodePaths to a bam file,
302  // and (b) it won't matter until we have the Panda-monium system in place,
303  // since you can't load a TexProjectorEffect from an egg file.
304 }
305 
306 /**
307  * Receives an array of pointers, one for each time manager->read_pointer()
308  * was called in fillin(). Returns the number of pointers processed.
309  */
311 complete_pointers(TypedWritable **p_list, BamReader *manager) {
312  int pi = RenderEffect::complete_pointers(p_list, manager);
313 
314  return pi;
315 }
316 
317 /**
318  * This function is called by the BamReader's factory when a new object of
319  * type TexProjectorEffect is encountered in the Bam file. It should create
320  * the TexProjectorEffect and extract its information from the file.
321  */
322 TypedWritable *TexProjectorEffect::
323 make_from_bam(const FactoryParams &params) {
325  DatagramIterator scan;
326  BamReader *manager;
327 
328  parse_params(params, scan, manager);
329  effect->fillin(scan, manager);
330 
331  return effect;
332 }
333 
334 /**
335  * This internal function is called by make_from_bam to read in all of the
336  * relevant data from the BamFile for the new TexProjectorEffect.
337  */
338 void TexProjectorEffect::
339 fillin(DatagramIterator &scan, BamReader *manager) {
340  RenderEffect::fillin(scan, manager);
341 
342  size_t num_stages = scan.get_uint16();
343 
344  // Since we don't support full reading and writing of TexProjectorEffects
345  // yet, this value had better be zero. If it's not, maybe we're trying to
346  // read a bam file that was generated by some future version of Panda that
347  // does support these things.
348  nassertv(num_stages == 0);
349 }
350 
351 /**
352  *
353  */
354 void TexProjectorEffect::StageDef::
355 set_to(const NodePath &to) {
356  _to = to;
357  if (!_to.is_empty() && _to.node()->is_of_type(LensNode::get_class_type())) {
358  DCAST_INTO_V(_to_lens_node, _to.node());
359  } else {
360  _to_lens_node = nullptr;
361  }
362 }
TexProjectorEffect::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: texProjectorEffect.cxx:292
nodePath.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Lens::get_projection_mat
const LMatrix4 & get_projection_mat(StereoChannel channel=SC_mono) const
Returns the complete transformation matrix from a 3-d point in space to a point on the film,...
Definition: lens.I:563
DatagramIterator::get_uint16
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
Definition: datagramIterator.I:145
RenderEffect
This is the base class for a number of special render effects that may be set on scene graph nodes to...
Definition: renderEffect.h:48
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
TypedWritable::complete_pointers
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().
Definition: typedWritable.cxx:81
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
TexProjectorEffect::complete_pointers
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition: texProjectorEffect.cxx:311
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
CullTraverser
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
TextureStage::get_name
get_name
Returns the name of this texture stage.
Definition: textureStage.h:188
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
texProjectorEffect.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Datagram::add_uint16
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
cullTraverserData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
CPT
CPT(RenderEffect) TexProjectorEffect
Constructs a TexProjectorEffect that modifies no stages at all.
Definition: texProjectorEffect.cxx:38
CullTraverserData
This collects together the pieces of data that are accumulated for each node while walking the scene ...
Definition: cullTraverserData.h:40
Lens
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
RenderEffect::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: renderEffect.cxx:283
Factory::register_factory
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:73
lensNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
texMatrixAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TexMatrixAttrib
Applies a transform matrix to UV's before they are rendered.
Definition: texMatrixAttrib.h:30
NodePath::fail
static NodePath fail()
Creates a NodePath with the ET_fail error type set.
Definition: nodePath.I:149
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TexProjectorEffect
This effect automatically applies a computed texture matrix to the specified texture stage,...
Definition: texProjectorEffect.h:49
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
config_pgraph.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureStage
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
parse_params
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275