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