Panda3D
Loading...
Searching...
No Matches
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
23CPT(RenderAttrib) TexMatrixAttrib::_empty_attrib;
24TypeHandle TexMatrixAttrib::_type_handle;
25int TexMatrixAttrib::_attrib_slot;
26
27/**
28 *
29 */
30TexMatrixAttrib::
31~TexMatrixAttrib() {
32}
33
34/**
35 * Constructs a TexMatrixAttrib that applies no stages at all.
36 */
37CPT(RenderAttrib) TexMatrixAttrib::
38make() {
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 */
54CPT(RenderAttrib) TexMatrixAttrib::
55make(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 */
69CPT(RenderAttrib) TexMatrixAttrib::
70make(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 */
78CPT(RenderAttrib) TexMatrixAttrib::
79make_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 */
88CPT(RenderAttrib) TexMatrixAttrib::
89add_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 */
103CPT(RenderAttrib) TexMatrixAttrib::
104remove_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 */
114const LMatrix4 &TexMatrixAttrib::
115get_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 */
123bool TexMatrixAttrib::
124is_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 */
133bool TexMatrixAttrib::
134has_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 */
142int TexMatrixAttrib::
143get_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 */
151TextureStage *TexMatrixAttrib::
152get_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 */
162const LMatrix4 &TexMatrixAttrib::
163get_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 */
171CPT(TransformState) TexMatrixAttrib::
172get_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 */
183void TexMatrixAttrib::
184output(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 */
209int TexMatrixAttrib::
210compare_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 */
251size_t TexMatrixAttrib::
252get_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 */
277CPT(RenderAttrib) TexMatrixAttrib::
278compose_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 */
343CPT(RenderAttrib) TexMatrixAttrib::
344invert_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 */
423void TexMatrixAttrib::
424register_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 */
433write_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 */
456complete_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 */
480TypedWritable *TexMatrixAttrib::
481make_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 */
496void TexMatrixAttrib::
497fillin(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.
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.
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...
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...
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.
get_default
Returns the default TextureStage that will be used for all texturing that does not name a particular ...
Indicates a coordinate-system transform on vertices.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
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.
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.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.