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 }
ordered_vector::size
size_type_0 size() const
Returns the number of elements in the ordered vector.
Definition: ordered_vector.I:221
TypeHandle::get_name
get_name
Returns the name of the type.
Definition: typeHandle.h:136
DatagramIterator::get_int32
int32_t get_int32()
Extracts a signed 32-bit integer.
Definition: datagramIterator.I:107
DatagramIterator::get_uint16
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
Definition: datagramIterator.I:145
ov_set::sort
void sort()
Maps to sort_unique().
Definition: ordered_vector.I:731
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
ordered_vector::empty
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
Definition: ordered_vector.I:240
RenderAttrib::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: renderAttrib.cxx:527
ordered_vector::begin
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
Definition: ordered_vector.I:41
textureStagePool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
BamWriter::write_pointer
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
RenderAttrib
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
TexMatrixAttrib::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: texMatrixAttrib.cxx:433
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
pointer_hash::add_hash
static size_t add_hash(size_t start, const void *key)
Adds the indicated key into a running hash.
Definition: stl_compares.I:110
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureStagePool::get_stage
static TextureStage * get_stage(TextureStage *temp)
Returns a TextureStage pointer that represents the same TextureStage described by temp,...
Definition: textureStagePool.I:31
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
ordered_vector::end
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
Definition: ordered_vector.I:50
CPT
CPT(RenderAttrib) TexMatrixAttrib
Constructs a TexMatrixAttrib that applies no stages at all.
Definition: texMatrixAttrib.cxx:37
BamWriter::get_file_minor_ver
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being written.
Definition: bamWriter.I:59
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
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
ordered_vector::push_back
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
Definition: ordered_vector.I:614
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
Datagram::add_int32
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:67
TexMatrixAttrib::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: texMatrixAttrib.cxx:456
texMatrixAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
integer_hash::add_hash
static size_t add_hash(size_t start, const Key &key)
Adds the indicated key into a running hash.
Definition: stl_compares.I:101
BamReader::read_pointer
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
TexMatrixAttrib
Applies a transform matrix to UV's before they are rendered.
Definition: texMatrixAttrib.h:30
BamReader::get_file_minor_ver
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureStage::get_default
get_default
Returns the default TextureStage that will be used for all texturing that does not name a particular ...
Definition: textureStage.h:207
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
graphicsStateGuardianBase.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