Panda3D

texGenAttrib.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 texGenAttrib.cxx
10 * @author masad
11 * @date 2004-06-21
12 */
13
14 #include "texGenAttrib.h"
15 #include "texturePool.h"
16 #include "graphicsStateGuardianBase.h"
17 #include "bamReader.h"
18 #include "bamWriter.h"
19 #include "datagram.h"
20 #include "datagramIterator.h"
21 #include "dcast.h"
22
23 CPT(RenderAttrib) TexGenAttrib::_empty_attrib;
24 TypeHandle TexGenAttrib::_type_handle;
25 int TexGenAttrib::_attrib_slot;
26
27 /**
28 *
29 */
30 TexGenAttrib::
31 ~TexGenAttrib() {
32 }
33
34 /**
35 * Constructs a TexGenAttrib that generates no stages at all.
36 */
37 CPT(RenderAttrib) TexGenAttrib::
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 TexGenAttrib);
43 }
44
45 return _empty_attrib;
46 }
47
48 /**
49 * Constructs a TexGenAttrib that generates just the indicated stage.
50 */
51 CPT(RenderAttrib) TexGenAttrib::
52 make(TextureStage *stage, TexGenAttrib::Mode mode) {
53 return DCAST(TexGenAttrib, make())->add_stage(stage, mode);
54 }
55
56 /**
57 * Returns a RenderAttrib that corresponds to whatever the standard default
58 * properties for render attributes of this type ought to be.
59 */
60 CPT(RenderAttrib) TexGenAttrib::
61 make_default() {
62 return return_new(new TexGenAttrib);
63 }
64
65 /**
66 * Returns a new TexGenAttrib just like this one, with the indicated
67 * generation mode for the given stage. If this stage already exists, its
68 * mode is replaced.
69 */
70 CPT(RenderAttrib) TexGenAttrib::
71 add_stage(TextureStage *stage, TexGenAttrib::Mode mode) const {
72 nassertr(mode != M_constant, this);
73
74 CPT(RenderAttrib) removed = remove_stage(stage);
75 TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed));
76
77 ModeDef &mode_def = attrib->_stages[stage];
78 mode_def._mode = mode;
79 attrib->record_stage(stage, mode_def);
80
81 return return_new(attrib);
82 }
83
84 /**
85 * Returns a new TexGenAttrib just like this one, with the indicated
86 * generation mode for the given stage. If this stage already exists, its
87 * mode is replaced.
88 *
89 * This variant also accepts constant_value, which is only meaningful if mode
90 * is M_constant.
91 */
92 CPT(RenderAttrib) TexGenAttrib::
93 add_stage(TextureStage *stage, TexGenAttrib::Mode mode,
94 const LTexCoord3 &constant_value) const {
95 nassertr(mode == M_constant, this);
96
97 CPT(RenderAttrib) removed = remove_stage(stage);
98 TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed));
99
100 ModeDef &mode_def = attrib->_stages[stage];
101 mode_def._mode = mode;
102 mode_def._constant_value = constant_value;
103 attrib->record_stage(stage, mode_def);
104
105 return return_new(attrib);
106 }
107
108 /**
109 * Returns a new TexGenAttrib just like this one, with the indicated stage
110 * removed.
111 */
112 CPT(RenderAttrib) TexGenAttrib::
113 remove_stage(TextureStage *stage) const {
114 Stages::const_iterator si;
115 si = _stages.find(stage);
116 if (si == _stages.end()) {
117 return this;
118 }
119
120 Mode mode = (*si).second._mode;
121 TexGenAttrib *attrib = new TexGenAttrib(*this);
122 attrib->_stages.erase(stage);
123 attrib->_no_texcoords.erase(stage);
124 if (mode == M_point_sprite) {
125 attrib->_num_point_sprites--;
126 if (attrib->_num_point_sprites == 0) {
127 attrib->_point_geom_rendering &= ~Geom::GR_point_sprite;
128 }
129 }
130 return return_new(attrib);
131 }
132
133 /**
134 * Returns true if no stages are defined in the TexGenAttrib, false if at
135 * least one is.
136 */
137 bool TexGenAttrib::
138 is_empty() const {
139 return _stages.empty();
140 }
141
142 /**
143 * Returns true if there is a mode associated with the indicated stage, or
144 * false otherwise (in which case get_transform(stage) will return M_off).
145 */
146 bool TexGenAttrib::
147 has_stage(TextureStage *stage) const {
148 Stages::const_iterator mi = _stages.find(stage);
149 return (mi != _stages.end());
150 }
151
152 /**
153 * Returns the generation mode associated with the named texture stage, or
154 * M_off if nothing is associated with the indicated stage.
155 */
156 TexGenAttrib::Mode TexGenAttrib::
157 get_mode(TextureStage *stage) const {
158 Stages::const_iterator mi = _stages.find(stage);
159 if (mi != _stages.end()) {
160 return (*mi).second._mode;
161 }
162 return M_off;
163 }
164
165 /**
166 * Returns true if the indicated TextureStage will have texture coordinates
167 * generated for it automatically (and thus there is no need to upload the
168 * texture coordinates encoded in the vertices).
169 */
170 bool TexGenAttrib::
171 has_gen_texcoord_stage(TextureStage *stage) const {
172 NoTexCoordStages::const_iterator mi = _no_texcoords.find(stage);
173 return (mi != _no_texcoords.end());
174 }
175
176 /**
177 * Returns the constant value associated with the named texture stage. This
178 * is only meaningful if the mode is M_constant.
179 */
180 const LTexCoord3 &TexGenAttrib::
181 get_constant_value(TextureStage *stage) const {
182 Stages::const_iterator mi = _stages.find(stage);
183 if (mi != _stages.end()) {
184 return (*mi).second._constant_value;
185 }
186 return LTexCoord3::zero();
187 }
188
189 /**
190 *
191 */
192 void TexGenAttrib::
193 output(std::ostream &out) const {
194 out << get_type() << ":";
195
196 Stages::const_iterator mi;
197 for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
198 TextureStage *stage = (*mi).first;
199 const ModeDef &mode_def = (*mi).second;
200 out << " " << stage->get_name() << "(";
201 switch (mode_def._mode) {
202 case M_off:
203 out << "off";
204 break;
205
206 case M_eye_sphere_map:
207 out << "eye_sphere_map";
208 break;
209
210 case M_world_cube_map:
211 out << "world_cube_map";
212 break;
213 case M_eye_cube_map:
214 out << "eye_cube_map";
215 break;
216
217 case M_world_normal:
218 out << "world_normal";
219 break;
220 case M_eye_normal:
221 out << "eye_normal";
222 break;
223
224 case M_world_position:
225 out << "world_position";
226 break;
227 case M_eye_position:
228 out << "eye_position";
229 break;
230
231 case M_point_sprite:
232 out << "point_sprite";
233 break;
234
235 case M_constant:
236 out << "constant: " << mode_def._constant_value;
237 break;
238
239 case M_unused:
240 case M_unused2:
241 break;
242 }
243 out << ")";
244 }
245 }
246
247 /**
248 * Intended to be overridden by derived TexGenAttrib types to return a unique
249 * number indicating whether this TexGenAttrib is equivalent to the other one.
250 *
251 * This should return 0 if the two TexGenAttrib objects are equivalent, a
252 * number less than zero if this one should be sorted before the other one,
253 * and a number greater than zero otherwise.
254 *
255 * This will only be called with two TexGenAttrib objects whose get_type()
256 * functions return the same.
257 */
258 int TexGenAttrib::
259 compare_to_impl(const RenderAttrib *other) const {
260 const TexGenAttrib *ta = (const TexGenAttrib *)other;
261
262 Stages::const_iterator ai, bi;
263 ai = _stages.begin();
264 bi = ta->_stages.begin();
265 while (ai != _stages.end() && bi != ta->_stages.end()) {
266 if ((*ai).first < (*bi).first) {
267 // This stage is in a but not in b.
268 return -1;
269
270 } else if ((*bi).first < (*ai).first) {
271 // This stage is in b but not in a.
272 return 1;
273
274 } else {
275 // This stage is in both; compare the stages.
276 int compare = (*ai).second.compare_to((*bi).second);
277 if (compare != 0) {
278 return compare;
279 }
280 ++ai;
281 ++bi;
282 }
283 }
284
285 if (bi != ta->_stages.end()) {
286 // a ran out first; b was longer.
287 return -1;
288 }
289
290 if (ai != _stages.end()) {
291 // b ran out first; a was longer.
292 return 1;
293 }
294
295 return 0;
296 }
297
298 /**
299 * Intended to be overridden by derived RenderAttrib types to return a unique
300 * hash for these particular properties. RenderAttribs that compare the same
301 * with compare_to_impl(), above, should return the same hash; RenderAttribs
302 * that compare differently should return a different hash.
303 */
304 size_t TexGenAttrib::
305 get_hash_impl() const {
306 size_t hash = 0;
307 Stages::const_iterator ri;
308 for (ri = _stages.begin(); ri != _stages.end(); ++ri) {
309 const TextureStage *stage = (*ri).first;
310 const ModeDef &mode_def = (*ri).second;
311
312 hash = pointer_hash::add_hash(hash, stage);
313 hash = int_hash::add_hash(hash, (int)mode_def._mode);
314 hash = string_hash::add_hash(hash, mode_def._source_name);
315 hash = mode_def._light.add_hash(hash);
316 hash = mode_def._constant_value.add_hash(hash);
317 }
318
319 return hash;
320 }
321
322 /**
323 * Intended to be overridden by derived RenderAttrib types to specify how two
324 * consecutive RenderAttrib objects of the same type interact.
325 *
326 * This should return the result of applying the other RenderAttrib to a node
327 * in the scene graph below this RenderAttrib, which was already applied. In
328 * most cases, the result is the same as the other RenderAttrib (that is, a
329 * subsequent RenderAttrib completely replaces the preceding one). On the
330 * other hand, some kinds of RenderAttrib (for instance, ColorTransformAttrib)
331 * might combine in meaningful ways.
332 */
333 CPT(RenderAttrib) TexGenAttrib::
334 compose_impl(const RenderAttrib *other) const {
335 const TexGenAttrib *ta = (const TexGenAttrib *)other;
336
337 // The composition is the union of the two attribs. In the case when a
338 // stage is in both attribs, we compose the stages.
339
340 TexGenAttrib *attrib = new TexGenAttrib;
341
342 Stages::const_iterator ai, bi;
343 ai = _stages.begin();
344 bi = ta->_stages.begin();
345 while (ai != _stages.end() && bi != ta->_stages.end()) {
346 if ((*ai).first < (*bi).first) {
347 // This stage is in a but not in b.
348 attrib->_stages.insert(attrib->_stages.end(), *ai);
349 ++ai;
350
351 } else if ((*bi).first < (*ai).first) {
352 // This stage is in b but not in a.
353 attrib->_stages.insert(attrib->_stages.end(), *bi);
354 ++bi;
355
356 } else {
357 // This stage is in both; b wins.
358 attrib->_stages.insert(attrib->_stages.end(), *bi);
359 ++bi;
360 ++ai;
361 }
362 }
363
364 while (ai != _stages.end()) {
365 // This stage is in a but not in b.
366 attrib->_stages.insert(attrib->_stages.end(), *ai);
367 ++ai;
368 }
369
370 while (bi != ta->_stages.end()) {
371 // This stage is in b but not in a.
372 attrib->_stages.insert(attrib->_stages.end(), *bi);
373 ++bi;
374 }
375
376 attrib->filled_stages();
377
378 return return_new(attrib);
379 }
380
381 /**
382 * Intended to be overridden by derived RenderAttrib types to specify how two
383 * consecutive RenderAttrib objects of the same type interact.
384 *
385 * See invert_compose() and compose_impl().
386 */
387 CPT(RenderAttrib) TexGenAttrib::
388 invert_compose_impl(const RenderAttrib *other) const {
389 const TexGenAttrib *ta = (const TexGenAttrib *)other;
390
391 // The inverse composition works a lot like the composition, except we
392 // invert the ai stages.
393
394 TexGenAttrib *attrib = new TexGenAttrib;
395
396 Stages::const_iterator ai, bi;
397 ai = _stages.begin();
398 bi = ta->_stages.begin();
399 while (ai != _stages.end() && bi != ta->_stages.end()) {
400 if ((*ai).first < (*bi).first) {
401 // This stage is in a but not in b. Turn a off.
402 attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, ModeDef()));
403 ++ai;
404
405 } else if ((*bi).first < (*ai).first) {
406 // This stage is in b but not in a.
407 attrib->_stages.insert(attrib->_stages.end(), *bi);
408 ++bi;
409
410 } else {
411 // This stage is in both; b wins.
412 attrib->_stages.insert(attrib->_stages.end(), *bi);
413 ++bi;
414 ++ai;
415 }
416 }
417
418 while (ai != _stages.end()) {
419 // This stage is in a but not in b.
420 attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, ModeDef()));
421 ++ai;
422 }
423
424 while (bi != ta->_stages.end()) {
425 // This stage is in b but not in a.
426 attrib->_stages.insert(attrib->_stages.end(), *bi);
427 ++bi;
428 }
429
430 attrib->filled_stages();
431
432 return return_new(attrib);
433 }
434
435 /**
436 * This method is to be called after the _stages map has been built up
437 * internally through some artificial means; it copies the appropriate
438 * settings to _no_texcoords and updates other internal cache values
439 * appropriately.
440 */
441 void TexGenAttrib::
442 filled_stages() {
443 Stages::iterator ri;
444 for (ri = _stages.begin(); ri != _stages.end(); ++ri) {
445 TextureStage *stage = (*ri).first;
446 ModeDef &mode_def = (*ri).second;
447 record_stage(stage, mode_def);
448 }
449 }
450
451 /**
452 * Updates the appropriate internal caches before adding the indicated stage
453 * with the given mode to the _stages map.
454 */
455 void TexGenAttrib::
456 record_stage(TextureStage *stage, TexGenAttrib::ModeDef &mode_def) {
457 switch (mode_def._mode) {
458 case M_point_sprite:
459 _no_texcoords.insert(stage);
460 _point_geom_rendering |= Geom::GR_point_sprite;
461 _num_point_sprites++;
462 break;
463
464 case M_off:
465 break;
466
467 default:
468 _no_texcoords.insert(stage);
469 }
470 }
471
472 /**
473 * Tells the BamReader how to create objects of type TexGenAttrib.
474 */
475 void TexGenAttrib::
476 register_with_read_factory() {
477 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
478 }
479
480 /**
481 * Writes the contents of this object to the datagram for shipping out to a
482 * Bam file.
483 */
484 void TexGenAttrib::
485 write_datagram(BamWriter *manager, Datagram &dg) {
486 RenderAttrib::write_datagram(manager, dg);
487
488 dg.add_uint16(_stages.size());
489
490 Stages::const_iterator si;
491 for (si = _stages.begin(); si != _stages.end(); ++si) {
492 TextureStage *stage = (*si).first;
493 Mode mode = (*si).second._mode;
494
495 manager->write_pointer(dg, stage);
496 dg.add_uint8((unsigned int)mode);
497 }
498 }
499
500 /**
501 * Receives an array of pointers, one for each time manager->read_pointer()
502 * was called in fillin(). Returns the number of pointers processed.
503 */
504 int TexGenAttrib::
505 complete_pointers(TypedWritable **p_list, BamReader *manager) {
506 int pi = RenderAttrib::complete_pointers(p_list, manager);
507
508 pvector<Mode>::const_iterator mi;
509 for (mi = _read_modes.begin(); mi != _read_modes.end(); ++mi) {
510 Mode mode = (*mi);
511
512 TextureStage *stage = DCAST(TextureStage, p_list[pi++]);
513 _stages[stage]._mode = mode;
514 }
515
516 filled_stages();
517
518 return pi;
519 }
520
521 /**
522 * This function is called by the BamReader's factory when a new object of
523 * type TexGenAttrib is encountered in the Bam file. It should create the
524 * TexGenAttrib and extract its information from the file.
525 */
526 TypedWritable *TexGenAttrib::
527 make_from_bam(const FactoryParams &params) {
528 TexGenAttrib *attrib = new TexGenAttrib;
529 DatagramIterator scan;
530 BamReader *manager;
531
532 parse_params(params, scan, manager);
533 attrib->fillin(scan, manager);
534
535 return attrib;
536 }
537
538 /**
539 * This internal function is called by make_from_bam to read in all of the
540 * relevant data from the BamFile for the new TexGenAttrib.
541 */
542 void TexGenAttrib::
543 fillin(DatagramIterator &scan, BamReader *manager) {
544 RenderAttrib::fillin(scan, manager);
545
546 size_t num_stages = scan.get_uint16();
547
548 // For now, read in a linear list of the modes we will assign to each
549 // associated TextureStage pointer. Later, in complete_pointers, we'll fill
550 // up the map the with appropriate TextureStageMode pairing.
551 _read_modes.clear();
552 _read_modes.reserve(num_stages);
553 for (size_t i = 0; i < num_stages; i++) {
554 manager->read_pointer(scan);
555 Mode mode = (Mode)scan.get_uint8();
556 _read_modes.push_back(mode);
557 }
558 }
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
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
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
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
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
DatagramIterator::get_uint8
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
Definition: datagramIterator.I:72
DatagramIterator::get_uint16
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
Definition: datagramIterator.I:145
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
Datagram::add_uint8
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:50
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
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
Geom
A container for geometry primitives.
Definition: geom.h:54
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
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
TexGenAttrib
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
Definition: texGenAttrib.h:32
TexGenAttrib::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: texGenAttrib.cxx:485
TexGenAttrib::register_with_read_factory
static void register_with_read_factory()
Tells the BamReader how to create objects of type TexGenAttrib.
Definition: texGenAttrib.cxx:476
TexGenAttrib::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: texGenAttrib.cxx:505
TextureStage
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
TextureStage::get_name
get_name
Returns the name of this texture stage.
Definition: textureStage.h:190
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
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
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
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
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
sequence_hash::add_hash
static size_t add_hash(size_t start, const Key &key)
Adds the elements of the indicated key into a running hash.
Definition: stl_compares.I:168
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
graphicsStateGuardianBase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT
CPT(RenderAttrib) TexGenAttrib
Constructs a TexGenAttrib that generates no stages at all.
Definition: texGenAttrib.cxx:37
texGenAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
texturePool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.