Panda3D
texMatrixAttrib.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 texMatrixAttrib.cxx
10  * @author drose
11  * @date 2002-03-14
12  */
13 
14 #include "texMatrixAttrib.h"
16 #include "dcast.h"
17 #include "bamReader.h"
18 #include "bamWriter.h"
19 #include "datagram.h"
20 #include "datagramIterator.h"
21 #include "textureStagePool.h"
22 
23 CPT(RenderAttrib) TexMatrixAttrib::_empty_attrib;
24 TypeHandle TexMatrixAttrib::_type_handle;
25 int TexMatrixAttrib::_attrib_slot;
26 
27 /**
28  *
29  */
30 TexMatrixAttrib::
31 ~TexMatrixAttrib() {
32 }
33 
34 /**
35  * Constructs a TexMatrixAttrib that applies no stages at all.
36  */
37 CPT(RenderAttrib) TexMatrixAttrib::
38 make() {
39  // We make it a special case and store a pointer to the empty attrib forever
40  // once we find it the first time, as an optimization.
41  if (_empty_attrib == nullptr) {
42  _empty_attrib = return_new(new TexMatrixAttrib);
43  }
44 
45  return _empty_attrib;
46 }
47 
48 /**
49  * Constructs a TexMatrixAttrib that applies the indicated matrix to the
50  * default texture stage. This interface is deprecated.
51  *
52  * @deprecated Use the constructor that takes a TextureStage instead.
53  */
54 CPT(RenderAttrib) TexMatrixAttrib::
55 make(const LMatrix4 &mat) {
56  pgraph_cat.warning()
57  << "Using deprecated TexMatrixAttrib interface.\n";
58  if (mat.is_identity()) {
59  return make();
60  }
61  CPT(TransformState) transform = TransformState::make_mat(mat);
62  return make(TextureStage::get_default(), transform);
63 }
64 
65 /**
66  * Constructs a TexMatrixAttrib that applies the indicated transform to the
67  * named texture stage.
68  */
69 CPT(RenderAttrib) TexMatrixAttrib::
70 make(TextureStage *stage, const TransformState *transform) {
71  return DCAST(TexMatrixAttrib, make())->add_stage(stage, transform);
72 }
73 
74 /**
75  * Returns a RenderAttrib that corresponds to whatever the standard default
76  * properties for render attributes of this type ought to be.
77  */
78 CPT(RenderAttrib) TexMatrixAttrib::
79 make_default() {
80  return return_new(new TexMatrixAttrib);
81 }
82 
83 /**
84  * Returns a new TexMatrixAttrib just like this one, with the indicated
85  * transform for the given stage. If this stage already exists, its transform
86  * is replaced.
87  */
88 CPT(RenderAttrib) TexMatrixAttrib::
89 add_stage(TextureStage *stage, const TransformState *transform,
90  int override) const {
91  TexMatrixAttrib *attrib = new TexMatrixAttrib(*this);
92  Stages::iterator si = attrib->_stages.insert(StageNode(stage)).first;
93  (*si)._transform = transform;
94  (*si)._override = override;
95 
96  return return_new(attrib);
97 }
98 
99 /**
100  * Returns a new TexMatrixAttrib just like this one, with the indicated stage
101  * removed.
102  */
103 CPT(RenderAttrib) TexMatrixAttrib::
104 remove_stage(TextureStage *stage) const {
105  TexMatrixAttrib *attrib = new TexMatrixAttrib(*this);
106  attrib->_stages.erase(StageNode(stage));
107  return return_new(attrib);
108 }
109 
110 /**
111  * Returns the transformation matrix associated with the default texture
112  * stage.
113  */
114 const LMatrix4 &TexMatrixAttrib::
115 get_mat() const {
116  return get_mat(TextureStage::get_default());
117 }
118 
119 /**
120  * Returns true if no stages are defined in the TexMatrixAttrib, false if at
121  * least one is.
122  */
123 bool TexMatrixAttrib::
124 is_empty() const {
125  return _stages.empty();
126 }
127 
128 /**
129  * Returns true if there is a transform associated with the indicated stage,
130  * or false otherwise (in which case get_transform(stage) will return the
131  * identity transform).
132  */
133 bool TexMatrixAttrib::
134 has_stage(TextureStage *stage) const {
135  Stages::const_iterator mi = _stages.find(StageNode(stage));
136  return (mi != _stages.end());
137 }
138 
139 /**
140  * Returns the number of stages that are represented by this attrib.
141  */
142 int TexMatrixAttrib::
143 get_num_stages() const {
144  return _stages.size();
145 }
146 
147 /**
148  * Returns the nth stage that is represented by this attrib. The
149  * TextureStages are in no particular order.
150  */
151 TextureStage *TexMatrixAttrib::
152 get_stage(int n) const {
153  nassertr(n >= 0 && n < (int)_stages.size(), nullptr);
154  return _stages[n]._stage;
155 }
156 
157 /**
158  * Returns the transformation matrix associated with the indicated texture
159  * stage, or identity matrix if nothing is associated with the indicated
160  * stage.
161  */
162 const LMatrix4 &TexMatrixAttrib::
163 get_mat(TextureStage *stage) const {
164  return get_transform(stage)->get_mat();
165 }
166 
167 /**
168  * Returns the transformation associated with the indicated texture stage, or
169  * identity matrix if nothing is associated with the indicated stage.
170  */
171 CPT(TransformState) TexMatrixAttrib::
172 get_transform(TextureStage *stage) const {
173  Stages::const_iterator mi = _stages.find(StageNode(stage));
174  if (mi != _stages.end()) {
175  return (*mi)._transform;
176  }
177  return TransformState::make_identity();
178 }
179 
180 /**
181  *
182  */
183 void TexMatrixAttrib::
184 output(std::ostream &out) const {
185  out << get_type() << ":";
186 
187  Stages::const_iterator mi;
188  for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
189  const StageNode &sn = (*mi);
190  out << " " << sn._stage->get_name() << "(" << *sn._transform << ")";
191  if (sn._override != 0) {
192  out << "^" << sn._override;
193  }
194  }
195 }
196 
197 /**
198  * Intended to be overridden by derived TexMatrixAttrib types to return a
199  * unique number indicating whether this TexMatrixAttrib is equivalent to the
200  * other one.
201  *
202  * This should return 0 if the two TexMatrixAttrib objects are equivalent, a
203  * number less than zero if this one should be sorted before the other one,
204  * and a number greater than zero otherwise.
205  *
206  * This will only be called with two TexMatrixAttrib objects whose get_type()
207  * functions return the same.
208  */
209 int TexMatrixAttrib::
210 compare_to_impl(const RenderAttrib *other) const {
211  const TexMatrixAttrib *ta = (const TexMatrixAttrib *)other;
212 
213  Stages::const_iterator ai, bi;
214  ai = _stages.begin();
215  bi = ta->_stages.begin();
216  while (ai != _stages.end() && bi != ta->_stages.end()) {
217  if ((*ai) < (*bi)) {
218  // This stage is in a but not in b.
219  return -1;
220 
221  } else if ((*bi) < (*ai)) {
222  // This stage is in b but not in a.
223  return 1;
224 
225  } else {
226  // This stage is in both.
227  ++ai;
228  ++bi;
229  }
230  }
231 
232  if (bi != ta->_stages.end()) {
233  // a ran out first; b was longer.
234  return -1;
235  }
236 
237  if (ai != _stages.end()) {
238  // b ran out first; a was longer.
239  return 1;
240  }
241 
242  return 0;
243 }
244 
245 /**
246  * Intended to be overridden by derived RenderAttrib types to return a unique
247  * hash for these particular properties. RenderAttribs that compare the same
248  * with compare_to_impl(), above, should return the same hash; RenderAttribs
249  * that compare differently should return a different hash.
250  */
251 size_t TexMatrixAttrib::
252 get_hash_impl() const {
253  size_t hash = 0;
254  Stages::const_iterator si;
255  for (si = _stages.begin(); si != _stages.end(); ++si) {
256  const StageNode &sn = (*si);
257 
258  hash = pointer_hash::add_hash(hash, sn._stage);
259  hash = pointer_hash::add_hash(hash, sn._transform);
260  hash = int_hash::add_hash(hash, sn._override);
261  }
262 
263  return hash;
264 }
265 
266 /**
267  * Intended to be overridden by derived RenderAttrib types to specify how two
268  * consecutive RenderAttrib objects of the same type interact.
269  *
270  * This should return the result of applying the other RenderAttrib to a node
271  * in the scene graph below this RenderAttrib, which was already applied. In
272  * most cases, the result is the same as the other RenderAttrib (that is, a
273  * subsequent RenderAttrib completely replaces the preceding one). On the
274  * other hand, some kinds of RenderAttrib (for instance, ColorTransformAttrib)
275  * might combine in meaningful ways.
276  */
277 CPT(RenderAttrib) TexMatrixAttrib::
278 compose_impl(const RenderAttrib *other) const {
279  const TexMatrixAttrib *ta = (const TexMatrixAttrib *)other;
280 
281  // The composition is the union of the two attribs. In the case when a
282  // stage is in both attribs, we compose the stages.
283 
284  TexMatrixAttrib *attrib = new TexMatrixAttrib;
285 
286  Stages::const_iterator ai, bi;
287  ai = _stages.begin();
288  bi = ta->_stages.begin();
289  while (ai != _stages.end() && bi != ta->_stages.end()) {
290  if ((*ai)._stage < (*bi)._stage) {
291  // This stage is in a but not in b.
292  attrib->_stages.insert(attrib->_stages.end(), *ai);
293  ++ai;
294 
295  } else if ((*bi)._stage < (*ai)._stage) {
296  // This stage is in b but not in a.
297  attrib->_stages.insert(attrib->_stages.end(), *bi);
298  ++bi;
299 
300  } else {
301  // This stage is in both.
302  if ((*ai)._override == (*bi)._override) {
303  // Same override; compose them.
304  CPT(TransformState) new_transform = (*ai)._transform->compose((*bi)._transform);
305  StageNode sn((*ai)._stage);
306  sn._transform = new_transform;
307  sn._override = (*ai)._override;
308  attrib->_stages.insert(attrib->_stages.end(), sn);
309  } else if ((*ai)._override < (*bi)._override) {
310  // Override b wins.
311  attrib->_stages.insert(attrib->_stages.end(), *bi);
312  } else {
313  // Override a wins.
314  attrib->_stages.insert(attrib->_stages.end(), *ai);
315  }
316 
317  ++ai;
318  ++bi;
319  }
320  }
321 
322  while (ai != _stages.end()) {
323  // This stage is in a but not in b.
324  attrib->_stages.insert(attrib->_stages.end(), *ai);
325  ++ai;
326  }
327 
328  while (bi != ta->_stages.end()) {
329  // This stage is in b but not in a.
330  attrib->_stages.insert(attrib->_stages.end(), *bi);
331  ++bi;
332  }
333 
334  return return_new(attrib);
335 }
336 
337 /**
338  * Intended to be overridden by derived RenderAttrib types to specify how two
339  * consecutive RenderAttrib objects of the same type interact.
340  *
341  * See invert_compose() and compose_impl().
342  */
343 CPT(RenderAttrib) TexMatrixAttrib::
344 invert_compose_impl(const RenderAttrib *other) const {
345  const TexMatrixAttrib *ta = (const TexMatrixAttrib *)other;
346 
347  // The inverse composition works a lot like the composition, except we
348  // invert the ai stages.
349 
350  TexMatrixAttrib *attrib = new TexMatrixAttrib;
351 
352  Stages::const_iterator ai, bi;
353  ai = _stages.begin();
354  bi = ta->_stages.begin();
355  while (ai != _stages.end() && bi != ta->_stages.end()) {
356  if ((*ai)._stage < (*bi)._stage) {
357  // This stage is in a but not in b.
358  CPT(TransformState) inv_a =
359  (*ai)._transform->invert_compose(TransformState::make_identity());
360  StageNode sn((*ai)._stage);
361  sn._transform = inv_a;
362  sn._override = (*ai)._override;
363  attrib->_stages.insert(attrib->_stages.end(), sn);
364  ++ai;
365 
366  } else if ((*bi)._stage < (*ai)._stage) {
367  // This stage is in b but not in a.
368  attrib->_stages.insert(attrib->_stages.end(), *bi);
369  ++bi;
370 
371  } else {
372  // This stage is in both.
373  if ((*ai)._override == (*bi)._override) {
374  // Same override; compose them.
375  CPT(TransformState) new_transform = (*ai)._transform->invert_compose((*bi)._transform);
376  StageNode sn((*ai)._stage);
377  sn._transform = new_transform;
378  sn._override = (*ai)._override;
379  attrib->_stages.insert(attrib->_stages.end(), sn);
380 
381  } else if ((*ai)._override < (*bi)._override) {
382  // Override b wins.
383  attrib->_stages.insert(attrib->_stages.end(), *bi);
384 
385  } else {
386  // Override a wins.
387  CPT(TransformState) inv_a =
388  (*ai)._transform->invert_compose(TransformState::make_identity());
389  StageNode sn((*ai)._stage);
390  sn._transform = inv_a;
391  sn._override = (*ai)._override;
392  attrib->_stages.insert(attrib->_stages.end(), sn);
393  }
394 
395  ++ai;
396  ++bi;
397  }
398  }
399 
400  while (ai != _stages.end()) {
401  // This stage is in a but not in b.
402  CPT(TransformState) inv_a =
403  (*ai)._transform->invert_compose(TransformState::make_identity());
404  StageNode sn((*ai)._stage);
405  sn._transform = inv_a;
406  sn._override = (*ai)._override;
407  attrib->_stages.insert(attrib->_stages.end(), sn);
408  ++ai;
409  }
410 
411  while (bi != ta->_stages.end()) {
412  // This stage is in b but not in a.
413  attrib->_stages.insert(attrib->_stages.end(), *bi);
414  ++bi;
415  }
416 
417  return return_new(attrib);
418 }
419 
420 /**
421  * Tells the BamReader how to create objects of type TexMatrixAttrib.
422  */
423 void TexMatrixAttrib::
424 register_with_read_factory() {
425  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
426 }
427 
428 /**
429  * Writes the contents of this object to the datagram for shipping out to a
430  * Bam file.
431  */
433 write_datagram(BamWriter *manager, Datagram &dg) {
434  RenderAttrib::write_datagram(manager, dg);
435 
436  dg.add_uint16(_stages.size());
437 
438  Stages::const_iterator si;
439  for (si = _stages.begin(); si != _stages.end(); ++si) {
440  const StageNode &sn = (*si);
441 
442  manager->write_pointer(dg, sn._stage);
443  manager->write_pointer(dg, sn._transform);
444 
445  if (manager->get_file_minor_ver() >= 24) {
446  dg.add_int32(sn._override);
447  }
448  }
449 }
450 
451 /**
452  * Receives an array of pointers, one for each time manager->read_pointer()
453  * was called in fillin(). Returns the number of pointers processed.
454  */
456 complete_pointers(TypedWritable **p_list, BamReader *manager) {
457  int pi = RenderAttrib::complete_pointers(p_list, manager);
458 
459  for (size_t sni = 0; sni < _stages.size(); ++sni) {
460  // Filter the TextureStage through the TextureStagePool.
461  PT(TextureStage) ts = DCAST(TextureStage, p_list[pi++]);
463 
464  const TransformState *transform = DCAST(TransformState, p_list[pi++]);
465 
466  StageNode &sn = _stages[sni];
467  sn._stage = ts;
468  sn._transform = transform;
469  }
470  _stages.sort();
471 
472  return pi;
473 }
474 
475 /**
476  * This function is called by the BamReader's factory when a new object of
477  * type TexMatrixAttrib is encountered in the Bam file. It should create the
478  * TexMatrixAttrib and extract its information from the file.
479  */
480 TypedWritable *TexMatrixAttrib::
481 make_from_bam(const FactoryParams &params) {
482  TexMatrixAttrib *attrib = new TexMatrixAttrib;
483  DatagramIterator scan;
484  BamReader *manager;
485 
486  parse_params(params, scan, manager);
487  attrib->fillin(scan, manager);
488 
489  return attrib;
490 }
491 
492 /**
493  * This internal function is called by make_from_bam to read in all of the
494  * relevant data from the BamFile for the new TexMatrixAttrib.
495  */
496 void TexMatrixAttrib::
497 fillin(DatagramIterator &scan, BamReader *manager) {
498  RenderAttrib::fillin(scan, manager);
499 
500  size_t num_stages = scan.get_uint16();
501  for (size_t i = 0; i < num_stages; i++) {
502  manager->read_pointer(scan);
503  manager->read_pointer(scan);
504  int override = 0;
505  if (manager->get_file_minor_ver() >= 24) {
506  override = scan.get_int32();
507  }
508 
509  StageNode sn(nullptr);
510  sn._override = override;
511  _stages.push_back(sn);
512  }
513 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:317
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being written.
Definition: bamWriter.I:59
A class to retrieve the individual data elements previously stored in a Datagram.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
int32_t get_int32()
Extracts a signed 32-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:67
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
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
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Applies a transform matrix to UV's before they are rendered.
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
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 TextureStage * get_stage(TextureStage *temp)
Returns a TextureStage pointer that represents the same TextureStage described by temp,...
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
get_default
Returns the default TextureStage that will be used for all texturing that does not name a particular ...
Definition: textureStage.h:207
Indicates a coordinate-system transform on vertices.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
get_name
Returns the name of the type.
Definition: typeHandle.h:136
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
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().
static size_t add_hash(size_t start, const Key &key)
Adds the indicated key into a running hash.
Definition: stl_compares.I:101
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
size_type_0 size() const
Returns the number of elements in the ordered vector.
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
void sort()
Maps to sort_unique().
static size_t add_hash(size_t start, const void *key)
Adds the indicated key into a running hash.
Definition: stl_compares.I:110
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT(RenderAttrib) TexMatrixAttrib
Constructs a TexMatrixAttrib that applies no stages at all.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.