Panda3D
geomNode.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 geomNode.cxx
10 * @author drose
11 * @date 2002-02-23
12 */
13
14#include "geomNode.h"
15#include "geom.h"
16#include "geomTransformer.h"
17#include "sceneGraphReducer.h"
18#include "stateMunger.h"
19#include "accumulatedAttribs.h"
20#include "colorAttrib.h"
21#include "colorScaleAttrib.h"
22#include "cullFaceAttrib.h"
23#include "texMatrixAttrib.h"
24#include "textureAttrib.h"
25#include "shaderAttrib.h"
26#include "bamReader.h"
27#include "bamWriter.h"
28#include "cullableObject.h"
29#include "cullHandler.h"
30#include "cullTraverser.h"
31#include "cullTraverserData.h"
32#include "datagram.h"
33#include "datagramIterator.h"
34#include "indent.h"
35#include "pset.h"
36#include "config_pgraph.h"
38#include "boundingBox.h"
39#include "boundingSphere.h"
40#include "config_mathutil.h"
42
43
44bool allow_flatten_color = ConfigVariableBool
45 ("allow-flatten-color", false,
46 PRC_DESC("allows color to always be flattened to vertices"));
47
48TypeHandle GeomNode::_type_handle;
49
50/**
51 *
52 */
53GeomNode::
54GeomNode(const std::string &name) :
55 PandaNode(name)
56{
57 _preserved = preserve_geom_nodes;
58
59 // GeomNodes have a certain set of bits on by default.
60 set_into_collide_mask(get_default_collide_mask());
61}
62
63/**
64 *
65 */
66GeomNode::
67GeomNode(const GeomNode &copy) :
68 PandaNode(copy),
69 _preserved(copy._preserved),
70 _cycler(copy._cycler)
71{
72}
73
74/**
75 *
76 */
77GeomNode::
78~GeomNode() {
79}
80
81/**
82 * Returns a newly-allocated PandaNode that is a shallow copy of this one. It
83 * will be a different pointer, but its internal data may or may not be shared
84 * with that of the original PandaNode. No children will be copied.
85 */
87make_copy() const {
88 return new GeomNode(*this);
89}
90
91/**
92 * Applies whatever attributes are specified in the AccumulatedAttribs object
93 * (and by the attrib_types bitmask) to the vertices on this node, if
94 * appropriate. If this node uses geom arrays like a GeomNode, the supplied
95 * GeomTransformer may be used to unify shared arrays across multiple
96 * different nodes.
97 *
98 * This is a generalization of xform().
99 */
101apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
102 GeomTransformer &transformer) {
103 if (pgraph_cat.is_debug()) {
104 pgraph_cat.debug()
105 << "Transforming geometry:\n";
106 attribs.write(pgraph_cat.debug(false), attrib_types, 2);
107 }
108
109 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
110 if (!attribs._transform->is_identity()) {
111 transformer.transform_vertices(this, attribs._transform->get_mat());
112 }
113 }
114
115 Thread *current_thread = Thread::get_current_thread();
116 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
117 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
118 PT(GeomList) geoms = cdata->modify_geoms();
119
120 // Iterate based on the number of geoms, not using STL iterators. This
121 // allows us to append to the list in the code below (which we might do
122 // when doublesiding polys) without visiting those new nodes during the
123 // traversal.
124 size_t num_geoms = geoms->size();
125 for (size_t i = 0; i < num_geoms; ++i) {
126 GeomEntry *entry = &(*geoms)[i];
127 PT(Geom) new_geom = entry->_geom.get_read_pointer()->make_copy();
128
129 AccumulatedAttribs geom_attribs = attribs;
130 entry->_state = geom_attribs.collect(entry->_state, attrib_types);
131
132 bool any_changed = false;
133
134 if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
135 CPT(RenderAttrib) ra = geom_attribs._color;
136 if (ra != nullptr) {
137 int override = geom_attribs._color_override;
138 entry->_state = entry->_state->add_attrib(ra, override);
139 }
140
141 ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
142 CPT (ColorAttrib) ca = DCAST(ColorAttrib, ra);
143 if (ca->get_color_type() != ColorAttrib::T_vertex) {
144 if(allow_flatten_color) {
145 if(transformer.set_color(new_geom, ca->get_color())) {
146 any_changed = true;
147 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
148 }
149 } else {
150 if (transformer.remove_column(new_geom, InternalName::get_color())) {
151 any_changed = true;
152 }
153 }
154 }
155 }
156 if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
157 if (geom_attribs._color_scale != nullptr) {
158 CPT(ColorScaleAttrib) csa = DCAST(ColorScaleAttrib, geom_attribs._color_scale);
159 if (csa->get_scale() != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
160
161
162 // Now, if we have an "off" or "flat" color attribute, we simply
163 // modify the color attribute, and leave the vertices alone.
164 CPT(RenderAttrib) ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
165 CPT(ColorAttrib) ca = DCAST(ColorAttrib, ra);
166 if(allow_flatten_color) {
167 if (transformer.transform_colors(new_geom, csa->get_scale())) {
168 any_changed = true;
169 }
170 } else {
171 if (ca->get_color_type() == ColorAttrib::T_off) {
172 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
173 // ColorAttrib::T_off means the color scale becomes the new
174 // color.
175 entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(csa->get_scale()));
176
177 } else if (ca->get_color_type() == ColorAttrib::T_flat) {
178 // ColorAttrib::T_flat means the color scale modulates the
179 // specified color to produce a new color.
180 const LColor &c1 = ca->get_color();
181 const LVecBase4 &c2 = csa->get_scale();
182 LColor color(c1[0] * c2[0], c1[1] * c2[1],
183 c1[2] * c2[2], c1[3] * c2[3]);
184 entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(color));
185
186 } else {
187 // Otherwise, we have vertex color, and we just scale it
188 // normally.
189 if (transformer.transform_colors(new_geom, csa->get_scale())) {
190 any_changed = true;
191 }
192 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
193 }
194 }
195 }
196 }
197 }
198
199 if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
200 if (geom_attribs._tex_matrix != nullptr) {
201 // Determine which texture coordinate names are used more than once.
202 // This assumes we have discovered all of the textures that are in
203 // effect on the GeomNode; this may not be true if there is a
204 // texture that has been applied at a node above that from which we
205 // started the flatten operation, but caveat programmer.
206 NameCount name_count;
207
208 if (geom_attribs._texture != nullptr) {
209 const TextureAttrib *ta = DCAST(TextureAttrib, geom_attribs._texture);
210 int num_on_stages = ta->get_num_on_stages();
211 for (int si = 0; si < num_on_stages; si++) {
212 TextureStage *stage = ta->get_on_stage(si);
213 const InternalName *name = stage->get_texcoord_name();
214 count_name(name_count, name);
215 }
216 }
217
218 const TexMatrixAttrib *tma =
219 DCAST(TexMatrixAttrib, geom_attribs._tex_matrix);
220
221 CPT(TexMatrixAttrib) new_tma = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
222
223 int num_stages = tma->get_num_stages();
224 for (int i = 0; i < num_stages; i++) {
225 TextureStage *stage = tma->get_stage(i);
226 InternalName *name = stage->get_texcoord_name();
227 if (get_name_count(name_count, name) > 1) {
228 // We can't transform these texcoords, since the name is used by
229 // more than one active stage.
230 new_tma = DCAST(TexMatrixAttrib, new_tma->add_stage(stage, tma->get_transform(stage)));
231
232 } else {
233 // It's safe to transform these texcoords; the name is used by
234 // no more than one active stage.
235 if (transformer.transform_texcoords(new_geom, name, name, tma->get_mat(stage))) {
236 any_changed = true;
237 }
238 }
239 }
240
241 if (!new_tma->is_empty()) {
242 entry->_state = entry->_state->add_attrib(new_tma);
243 }
244 }
245 }
246
247 if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
248 entry->_state = geom_attribs._other->compose(entry->_state);
249 }
250
251 // We handle cull_face last, since that might involve duplicating the
252 // geom, and we'd also like to duplicate all of the changes we may have
253 // applied in the above.
254
255 if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
256 if (geom_attribs._cull_face != nullptr) {
257 const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, geom_attribs._cull_face);
258 CullFaceAttrib::Mode mode = cfa->get_effective_mode();
259 switch (mode) {
260 case CullFaceAttrib::M_cull_none:
261 // Doublesided polys. Duplicate them.
262 {
263 bool has_normals = (new_geom->get_vertex_data()->has_column(InternalName::get_normal()));
264 if (has_normals) {
265 // If the geometry has normals, we have to duplicate it to
266 // reverse the normals on the duplicate copy.
267 PT(Geom) dup_geom = new_geom->reverse();
268 transformer.reverse_normals(dup_geom);
269
270 geoms->push_back(GeomEntry(dup_geom, entry->_state));
271
272 // The above push_back() operation might have invalidated our
273 // old pointer into the list, so we reassign it now.
274 entry = &(*geoms)[i];
275
276 } else {
277 // If there are no normals, we can just doubleside it in
278 // place. This is preferable because we can share vertices.
279 new_geom->doubleside_in_place();
280 any_changed = true;
281 }
282 }
283 break;
284
285 case CullFaceAttrib::M_cull_counter_clockwise:
286 // Reverse winding order.
287 new_geom->reverse_in_place();
288 transformer.reverse_normals(new_geom);
289 any_changed = true;
290 break;
291
292 default:
293 break;
294 }
295 }
296 }
297
298 if (any_changed) {
299 entry->_geom = new_geom;
300 }
301 }
302 }
303 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
304
305 if ((attrib_types & SceneGraphReducer::TT_apply_texture_color) != 0) {
306 transformer.apply_texture_colors(this, attribs._other);
307 }
308
309 transformer.register_vertices(this, false);
310}
311
312/**
313 * Transforms the contents of this node by the indicated matrix, if it means
314 * anything to do so. For most kinds of nodes, this does nothing.
315 *
316 * For a GeomNode, this does the right thing, but it is better to use a
317 * GeomTransformer instead, since it will share the new arrays properly
318 * between different GeomNodes.
319 */
321xform(const LMatrix4 &mat) {
322 GeomTransformer transformer;
323 transformer.transform_vertices(this, mat);
324}
325
326
327/**
328 * Returns true if it is generally safe to flatten out this particular kind of
329 * PandaNode by duplicating instances (by calling dupe_for_flatten()), false
330 * otherwise (for instance, a Camera cannot be safely flattened, because the
331 * Camera pointer itself is meaningful).
332 */
334safe_to_flatten() const {
335 if (_preserved) {
336 return false;
337 }
338
339 return true;
340}
341
342/**
343 * Returns true if it is generally safe to combine this particular kind of
344 * PandaNode with other kinds of PandaNodes of compatible type, adding
345 * children or whatever. For instance, an LODNode should not be combined with
346 * any other PandaNode, because its set of children is meaningful.
347 */
349safe_to_combine() const {
350 if (_preserved) {
351 return false;
352 }
353
354 return true;
355}
356
357/**
358 * The recursive implementation of prepare_scene(). Don't call this directly;
359 * call PandaNode::prepare_scene() or NodePath::prepare_scene() instead.
360 */
363 GeomTransformer &transformer, Thread *current_thread) {
364 PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects();
365
366 CDReader cdata(_cycler, current_thread);
367 GeomList::const_iterator gi;
368 CPT(GeomList) geoms = cdata->get_geoms();
369 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
370 const GeomEntry &entry = (*gi);
371 CPT(RenderState) geom_state = node_state->compose(entry._state);
372 CPT(Geom) geom = entry._geom.get_read_pointer();
373
374 // Munge the geom as required by the GSG.
375 PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
376 geom = transformer.premunge_geom(geom, munger);
377
378 // Prepare each of the vertex arrays in the munged Geom.
379 CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(false, current_thread);
380 GeomVertexDataPipelineReader vdata_reader(vdata, current_thread);
381 int num_arrays = vdata_reader.get_num_arrays();
382 for (int i = 0; i < num_arrays; ++i) {
383 CPT(GeomVertexArrayData) array = vdata_reader.get_array(i);
384 prepared_objects->enqueue_vertex_buffer((GeomVertexArrayData *)array.p());
385 }
386
387 // And also each of the index arrays.
388 int num_primitives = geom->get_num_primitives();
389 for (int i = 0; i < num_primitives; ++i) {
390 CPT(GeomPrimitive) prim = geom->get_primitive(i);
391 prepared_objects->enqueue_index_buffer((GeomPrimitive *)prim.p());
392 }
393
394 if (munger->is_of_type(StateMunger::get_class_type())) {
395 StateMunger *state_munger = (StateMunger *)munger.p();
396 geom_state = state_munger->munge_state(geom_state);
397 }
398
399 // As well as the shaders.
400 const ShaderAttrib *sa;
401 if (geom_state->get_attrib(sa)) {
402 Shader *shader = (Shader *)sa->get_shader();
403 if (shader != nullptr) {
404 prepared_objects->enqueue_shader(shader);
405 }
406 else if (sa->auto_shader()) {
407 gsg->ensure_generated_shader(geom_state);
408 }
409 else if (munger->is_of_type(StateMunger::get_class_type())) {
410 // Premunge the state for the fixed-function pipeline.
411 StateMunger *state_munger = (StateMunger *)munger.p();
412 geom_state = state_munger->munge_state(geom_state);
413 }
414 // TODO: prepare the shader inputs.
415 }
416
417 // And now prepare each of the textures.
418 const TextureAttrib *ta;
419 if (geom_state->get_attrib(ta)) {
420 int num_stages = ta->get_num_on_stages();
421 for (int i = 0; i < num_stages; ++i) {
422 Texture *texture = ta->get_on_texture(ta->get_on_stage(i));
423 // TODO: prepare the sampler states, if specified.
424 if (texture != nullptr) {
425 prepared_objects->enqueue_texture(texture);
426 }
427 }
428 }
429 }
430
431 PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
432}
433
434
435/**
436 * Collapses this node with the other node, if possible, and returns a pointer
437 * to the combined node, or NULL if the two nodes cannot safely be combined.
438 *
439 * The return value may be this, other, or a new node altogether.
440 *
441 * This function is called from GraphReducer::flatten(), and need not deal
442 * with children; its job is just to decide whether to collapse the two nodes
443 * and what the collapsed node should look like.
444 */
446combine_with(PandaNode *other) {
447 if (is_exact_type(get_class_type()) &&
448 other->is_exact_type(get_class_type())) {
449 // Two GeomNodes can combine by moving Geoms from one to the other.
450 GeomNode *gother = DCAST(GeomNode, other);
451 add_geoms_from(gother);
452 return this;
453 }
454
455 return PandaNode::combine_with(other);
456}
457
458/**
459 * This is used to support NodePath::calc_tight_bounds(). It is not intended
460 * to be called directly, and it has nothing to do with the normal Panda
461 * bounding-volume computation.
462 *
463 * If the node contains any geometry, this updates min_point and max_point to
464 * enclose its bounding box. found_any is to be set true if the node has any
465 * geometry at all, or left alone if it has none. This method may be called
466 * over several nodes, so it may enter with min_point, max_point, and
467 * found_any already set.
468 */
470calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
471 const TransformState *transform, Thread *current_thread) const {
472 CPT(TransformState) next_transform =
473 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
474 current_thread);
475
476 const LMatrix4 &mat = next_transform->get_mat();
477
478 CDReader cdata(_cycler, current_thread);
479 GeomList::const_iterator gi;
480 CPT(GeomList) geoms = cdata->get_geoms();
481 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
482 CPT(Geom) geom = (*gi)._geom.get_read_pointer();
483 geom->calc_tight_bounds(min_point, max_point, found_any,
484 geom->get_animated_vertex_data(true, current_thread),
485 !next_transform->is_identity(), mat,
486 current_thread);
487 }
488
489 return next_transform;
490}
491
492/**
493 * Returns true if there is some value to visiting this particular node during
494 * the cull traversal for any camera, false otherwise. This will be used to
495 * optimize the result of get_net_draw_show_mask(), so that any subtrees that
496 * contain only nodes for which is_renderable() is false need not be visited.
497 */
498bool GeomNode::
499is_renderable() const {
500 return true;
501}
502
503/**
504 * Adds the node's contents to the CullResult we are building up during the
505 * cull traversal, so that it will be drawn at render time. For most nodes
506 * other than GeomNodes, this is a do-nothing operation.
507 */
508void GeomNode::
510 trav->_geom_nodes_pcollector.add_level(1);
511
512 if (pgraph_cat.is_spam()) {
513 pgraph_cat.spam()
514 << "Found " << *this << " in state " << *data._state
515 << " draw_mask = " << data._draw_mask << "\n";
516 }
517
518 Thread *current_thread = trav->get_current_thread();
519
520 // Get all the Geoms, with no decalling.
521 Geoms geoms = get_geoms(current_thread);
522 int num_geoms = geoms.get_num_geoms();
523 trav->_geoms_pcollector.add_level(num_geoms);
524 CPT(TransformState) internal_transform = data.get_internal_transform(trav);
525
526 for (int i = 0; i < num_geoms; i++) {
527 CPT(Geom) geom = geoms.get_geom(i);
528 if (geom->is_empty()) {
529 continue;
530 }
531
532 CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
533 if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
534 // Cull.
535 continue;
536 }
537
538 // Cull the Geom bounding volume against the view frustum andor the cull
539 // planes. Don't bother unless we've got more than one Geom, since
540 // otherwise the bounding volume of the GeomNode is (probably) the same as
541 // that of the one Geom, and we've already culled against that.
542 if (num_geoms > 1) {
543 if (data._view_frustum != nullptr) {
544 // Cull the individual Geom against the view frustum.
545 CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
546 const GeometricBoundingVolume *geom_gbv =
547 geom_volume->as_geometric_bounding_volume();
548
549 int result = data._view_frustum->contains(geom_gbv);
550 if (result == BoundingVolume::IF_no_intersection) {
551 // Cull this Geom.
552 continue;
553 }
554 }
555 if (!data._cull_planes->is_empty()) {
556 // Also cull the Geom against the cull planes.
557 CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
558 const GeometricBoundingVolume *geom_gbv =
559 geom_volume->as_geometric_bounding_volume();
560 int result;
561 data._cull_planes->do_cull(result, state, geom_gbv);
562 if (result == BoundingVolume::IF_no_intersection) {
563 // Cull.
564 continue;
565 }
566 }
567 }
568
569 CullableObject *object =
570 new CullableObject(std::move(geom), std::move(state), internal_transform);
571 trav->get_cull_handler()->record_object(object, trav);
572 }
573}
574
575/**
576 * Returns the subset of CollideMask bits that may be set for this particular
577 * type of PandaNode. For most nodes, this is 0; it doesn't make sense to set
578 * a CollideMask for most kinds of nodes.
579 *
580 * For nodes that can be collided with, such as GeomNode and CollisionNode,
581 * this returns all bits on.
582 */
585 return CollideMask::all_on();
586}
587
588/**
589 * Adds a new Geom to the node. The geom is given the indicated state (which
590 * may be RenderState::make_empty(), to completely inherit its state from the
591 * scene graph).
592 */
594add_geom(Geom *geom, const RenderState *state) {
595 nassertv(geom != nullptr);
596 nassertv(geom->check_valid());
597 nassertv(state != nullptr);
598
599 Thread *current_thread = Thread::get_current_thread();
600 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
601 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
602
603 cdata->modify_geoms()->push_back(GeomEntry(geom, state));
604 }
605 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
606
607 mark_internal_bounds_stale();
608}
609
610/**
611 * Copies the Geoms (and their associated RenderStates) from the indicated
612 * GeomNode into this one.
613 */
615add_geoms_from(const GeomNode *other) {
616 Thread *current_thread = Thread::get_current_thread();
617 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
618 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
619 CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
620
621 GeomList::const_iterator gi;
622 CPT(GeomList) other_geoms = cdata_other->get_geoms();
623 PT(GeomList) this_geoms = cdata->modify_geoms();
624 for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) {
625 const GeomEntry &entry = (*gi);
626 nassertv(entry._geom.get_read_pointer()->check_valid());
627 this_geoms->push_back(entry);
628 }
629 }
630 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
631
632 mark_internal_bounds_stale();
633}
634
635/**
636 * Replaces the nth Geom of the node with a new pointer. There must already
637 * be a Geom in this slot.
638 *
639 * Note that if this method is called in a downstream stage (for instance,
640 * during cull or draw), then it will propagate the new list of Geoms upstream
641 * all the way to pipeline stage 0, which may step on changes that were made
642 * independently in pipeline stage 0. Use with caution.
643 */
645set_geom(int n, Geom *geom) {
646 nassertv(geom != nullptr);
647 nassertv(geom->check_valid());
648
649 CDWriter cdata(_cycler, true);
650 PT(GeomList) geoms = cdata->modify_geoms();
651 nassertv(n >= 0 && n < (int)geoms->size());
652 (*geoms)[n]._geom = geom;
653
654 mark_internal_bounds_stale();
655}
656
657/**
658 * Verifies that the each Geom within the GeomNode reference vertices that
659 * actually exist within its GeomVertexData. Returns true if the GeomNode
660 * appears to be valid, false otherwise.
661 */
663check_valid() const {
664 int num_geoms = get_num_geoms();
665 for (int i = 0; i < num_geoms; i++) {
666 const Geom *geom = get_geom(i);
667 if (!geom->check_valid()) {
668 return false;
669 }
670 }
671
672 return true;
673}
674
675/**
676 * Calls decompose() on each Geom with the GeomNode. This decomposes higher-
677 * order primitive types, like triangle strips, into lower-order types like
678 * indexed triangles. Normally there is no reason to do this, but it can be
679 * useful as an early preprocessing step, to allow a later call to unify() to
680 * proceed more quickly.
681 *
682 * See also SceneGraphReducer::decompose(), which is the normal way this is
683 * called.
684 */
686decompose() {
687 Thread *current_thread = Thread::get_current_thread();
688 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
689 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
690
691 GeomList::iterator gi;
692 PT(GeomList) geoms = cdata->modify_geoms();
693 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
694 GeomEntry &entry = (*gi);
695 nassertv(entry._geom.test_ref_count_integrity());
696 PT(Geom) geom = entry._geom.get_write_pointer();
697 geom->decompose_in_place();
698 }
699 }
700 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
701}
702
703/**
704 * Attempts to unify all of the Geoms contained within this node into a single
705 * Geom, or at least as few Geoms as possible. In turn, the individual
706 * GeomPrimitives contained within each resulting Geom are also unified. The
707 * goal is to reduce the number of GeomPrimitives within the node as far as
708 * possible. This may result in composite primitives, such as triangle strips
709 * and triangle fans, being decomposed into triangles. See also
710 * Geom::unify().
711 *
712 * max_indices represents the maximum number of indices that will be put in
713 * any one GeomPrimitive. If preserve_order is true, then the primitives will
714 * not be reordered during the operation, even if this results in a suboptimal
715 * result.
716 *
717 * In order for this to be successful, the primitives must reference the same
718 * GeomVertexData, have the same fundamental primitive type, and have
719 * compatible shade models.
720 */
722unify(int max_indices, bool preserve_order) {
723 bool any_changed = false;
724
725 Thread *current_thread = Thread::get_current_thread();
726 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
727 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
728
729 PT(GeomList) new_geoms = new GeomList;
730
731 // Try to unify each Geom with each preceding Geom. This is an n^2
732 // operation, but usually there are only a handful of Geoms to consider,
733 // so that's not a big deal.
734 GeomList::const_iterator gi;
735 CPT(GeomList) old_geoms = cdata->get_geoms();
736 for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) {
737 const GeomEntry &old_entry = (*gi);
738
739 bool unified = false;
740
741 // Go from back to front, to minimize damage to the primitive ordering.
742 GeomList::reverse_iterator gj;
743 for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) {
744 GeomEntry &new_entry = (*gj);
745 if (old_entry._state == new_entry._state) {
746 // Both states match, so try to combine the primitives.
747 CPT(Geom) old_geom = old_entry._geom.get_read_pointer();
748 PT(Geom) new_geom = new_entry._geom.get_write_pointer();
749 if (new_geom->copy_primitives_from(old_geom)) {
750 // Successfully combined!
751 unified = true;
752 any_changed = true;
753 }
754 }
755
756 if (preserve_order) {
757 // If we're insisting on preserving the order, we can only attempt
758 // to merge with the tail of the list.
759 break;
760 }
761 }
762
763 if (!unified) {
764 // Couldn't unify this Geom with anything, so just add it to the
765 // output list.
766 new_geoms->push_back(old_entry);
767 }
768 }
769
770 // Done! We'll keep whatever's left in the output list.
771 cdata->set_geoms(new_geoms);
772
773 // Finally, go back through and unify the resulting geom(s).
774 GeomList::iterator wgi;
775 for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) {
776 GeomEntry &entry = (*wgi);
777 nassertv(entry._geom.test_ref_count_integrity());
778 PT(Geom) geom = entry._geom.get_write_pointer();
779 geom->unify_in_place(max_indices, preserve_order);
780 }
781 }
782 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
783
784 if (any_changed) {
785 mark_internal_bounds_stale();
786 }
787}
788
789/**
790 * Writes a short description of all the Geoms in the node.
791 */
793write_geoms(std::ostream &out, int indent_level) const {
794 CDReader cdata(_cycler);
795 write(out, indent_level);
796 GeomList::const_iterator gi;
797 CPT(GeomList) geoms = cdata->get_geoms();
798 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
799 const GeomEntry &entry = (*gi);
800 indent(out, indent_level + 2)
801 << *entry._geom.get_read_pointer() << " " << *entry._state << "\n";
802 }
803}
804
805/**
806 * Writes a detailed description of all the Geoms in the node.
807 */
809write_verbose(std::ostream &out, int indent_level) const {
810 CDReader cdata(_cycler);
811 write(out, indent_level);
812 GeomList::const_iterator gi;
813 CPT(GeomList) geoms = cdata->get_geoms();
814 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
815 const GeomEntry &entry = (*gi);
816 CPT(Geom) geom = entry._geom.get_read_pointer();
817 indent(out, indent_level + 2)
818 << *geom << " " << *entry._state << "\n";
819 geom->write(out, indent_level + 4);
820 }
821}
822
823/**
824 *
825 */
826void GeomNode::
827output(std::ostream &out) const {
828 // Accumulate the total set of RenderAttrib types that are applied to any of
829 // our Geoms, so we can output them too. The result will be the list of
830 // attrib types that might be applied to some Geoms, but not necessarily to
831 // all Geoms.
832
833 CDReader cdata(_cycler);
834
835 pset<TypeHandle> attrib_types;
836
837 GeomList::const_iterator gi;
838 CPT(RenderState) common = RenderState::make_empty();
839
840 CPT(GeomList) geoms = cdata->get_geoms();
841 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
842 const GeomEntry &entry = (*gi);
843 common = common->compose(entry._state);
844 }
845
846 PandaNode::output(out);
847 out << " (" << geoms->size() << " geoms";
848
849 if (!common->is_empty()) {
850 out << ": " << *common;
851 }
852
853 out << ")";
854}
855
856/**
857 * A simple downcast check. Returns true if this kind of node happens to
858 * inherit from GeomNode, false otherwise.
859 *
860 * This is provided as a a faster alternative to calling
861 * is_of_type(GeomNode::get_class_type()), since this test is so important to
862 * rendering.
863 */
865is_geom_node() const {
866 return true;
867}
868
869/**
870 * Uses the indicated GSG to premunge the Geoms in this node to optimize them
871 * for eventual rendering. See SceneGraphReducer::premunge().
872 */
875 const RenderState *node_state,
876 GeomTransformer &transformer) {
877 Thread *current_thread = Thread::get_current_thread();
878
879 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
880 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
881
882 GeomList::iterator gi;
883 PT(GeomList) geoms = cdata->modify_geoms();
884 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
885 GeomEntry &entry = (*gi);
886 CPT(RenderState) geom_state = node_state->compose(entry._state);
887 CPT(Geom) geom = entry._geom.get_read_pointer();
888 PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
889 entry._geom = transformer.premunge_geom(geom, munger);
890 }
891 }
892 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
893}
894
895/**
896 * Recursively calls Geom::mark_bounds_stale() on every Geom at this node and
897 * below.
898 */
899void GeomNode::
900r_mark_geom_bounds_stale(Thread *current_thread) {
901 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
902 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
903
904 GeomList::iterator gi;
905 PT(GeomList) geoms = cdata->modify_geoms();
906 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
907 GeomEntry &entry = (*gi);
908 entry._geom.get_read_pointer()->mark_bounds_stale();
909 }
910 }
911 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
912 mark_internal_bounds_stale();
913
914 PandaNode::r_mark_geom_bounds_stale(current_thread);
915}
916
917/**
918 * Returns a newly-allocated BoundingVolume that represents the internal
919 * contents of the node. Should be overridden by PandaNode classes that
920 * contain something internally.
921 */
922void GeomNode::
923compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
924 int &internal_vertices,
925 int pipeline_stage,
926 Thread *current_thread) const {
927 int num_vertices = 0;
928
929 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
930
932 pvector<CPT(BoundingVolume) > child_volumes_ref;
933 bool all_box = true;
934
935 GeomList::const_iterator gi;
936 CPT(GeomList) geoms = cdata->get_geoms();
937 child_volumes.reserve(geoms->size());
938 child_volumes_ref.reserve(geoms->size());
939
940 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
941 const GeomEntry &entry = (*gi);
942 CPT(Geom) geom = entry._geom.get_read_pointer();
943 CPT(BoundingVolume) volume = geom->get_bounds();
944
945 if (!volume->is_empty()) {
946 child_volumes.push_back(volume);
947 child_volumes_ref.push_back(volume);
948 if (!volume->is_exact_type(BoundingBox::get_class_type())) {
949 all_box = false;
950 }
951 }
952 num_vertices += geom->get_nested_vertices();
953 }
954
956
957 BoundingVolume::BoundsType btype = get_bounds_type();
958 if (btype == BoundingVolume::BT_default) {
959 btype = bounds_type;
960 }
961
962 if (btype == BoundingVolume::BT_box ||
963 (btype != BoundingVolume::BT_sphere && all_box)) {
964 // If all of the child volumes are a BoundingBox, then our volume is also
965 // a BoundingBox.
966 gbv = new BoundingBox;
967 } else {
968 // Otherwise, it's a sphere.
969 gbv = new BoundingSphere;
970 }
971
972 if (child_volumes.size() > 0) {
973 const BoundingVolume **child_begin = &child_volumes[0];
974 const BoundingVolume **child_end = child_begin + child_volumes.size();
975 ((BoundingVolume *)gbv)->around(child_begin, child_end);
976 }
977
978 internal_bounds = gbv;
979 internal_vertices = num_vertices;
980}
981
982/**
983 * Tells the BamReader how to create objects of type GeomNode.
984 */
987 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
988}
989
990/**
991 * Writes the contents of this object to the datagram for shipping out to a
992 * Bam file.
993 */
995write_datagram(BamWriter *manager, Datagram &dg) {
996 PandaNode::write_datagram(manager, dg);
997 manager->write_cdata(dg, _cycler);
998}
999
1000/**
1001 * Called by the BamReader to perform any final actions needed for setting up
1002 * the object after all objects have been read and all pointers have been
1003 * completed.
1004 */
1006finalize(BamReader *manager) {
1007 if (manager->get_file_minor_ver() < 14) {
1008 // With version 6.14, we changed the default ColorAttrib behavior from
1009 // make_vertex() to make_flat(). This means that every Geom that contains
1010 // vertex colors now needs to have an explicit ColorAttrib::make_vertex()
1011 // on its state.
1012
1013 // Since we shouldn't override a different ColorAttrib inherited from
1014 // above, we create this new attrib with an override of -1.
1015
1016 CPT(InternalName) color = InternalName::get_color();
1017 CPT(RenderAttrib) vertex_color = ColorAttrib::make_vertex();
1018
1019 Thread *current_thread = Thread::get_current_thread();
1020 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1021 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1022
1023 GeomList::iterator gi;
1024 PT(GeomList) geoms = cdata->modify_geoms();
1025 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1026 GeomEntry &entry = (*gi);
1027 CPT(Geom) geom = entry._geom.get_read_pointer();
1028
1029 // Force the various GeomVertexArrayFormat objects to finalize
1030 // themselves. We have to do this before we can reliably call
1031 // GeomVertexData::has_column().
1032 CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
1033 CPT(GeomVertexFormat) vformat = vdata->get_format();
1034 for (size_t i = 0; i < vformat->get_num_arrays(); ++i) {
1035 const GeomVertexArrayFormat *varray = vformat->get_array(i);
1036 manager->finalize_now((GeomVertexArrayFormat *)varray);
1037 }
1038
1039 if (vdata->has_column(color) &&
1040 !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
1041 // We'll be reassigning the RenderState. Therefore, save it
1042 // temporarily to increment its reference count.
1043 PT(BamAuxData) aux_data = new BamAuxData;
1044 aux_data->_hold_state = entry._state;
1045 manager->set_aux_data((RenderState *)entry._state.p(), "hold_state", aux_data);
1046
1047 entry._state = entry._state->add_attrib(vertex_color, -1);
1048 }
1049 }
1050 }
1051 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1052 }
1053}
1054
1055/**
1056 * This function is called by the BamReader's factory when a new object of
1057 * type GeomNode is encountered in the Bam file. It should create the
1058 * GeomNode and extract its information from the file.
1059 */
1060TypedWritable *GeomNode::
1061make_from_bam(const FactoryParams &params) {
1062 GeomNode *node = new GeomNode("");
1063 DatagramIterator scan;
1064 BamReader *manager;
1065
1066 parse_params(params, scan, manager);
1067 node->fillin(scan, manager);
1068
1069 if (manager->get_file_minor_ver() < 14) {
1070 manager->register_finalize(node);
1071 }
1072
1073 return node;
1074}
1075
1076/**
1077 * This internal function is called by make_from_bam to read in all of the
1078 * relevant data from the BamFile for the new GeomNode.
1079 */
1080void GeomNode::
1081fillin(DatagramIterator &scan, BamReader *manager) {
1082 PandaNode::fillin(scan, manager);
1083 manager->read_cdata(scan, _cycler);
1084}
1085
1086/**
1087 *
1088 */
1089GeomNode::CData::
1090CData(const GeomNode::CData &copy) :
1091 _geoms(copy._geoms)
1092{
1093}
1094
1095/**
1096 *
1097 */
1098CycleData *GeomNode::CData::
1099make_copy() const {
1100 return new CData(*this);
1101}
1102
1103/**
1104 * Writes the contents of this object to the datagram for shipping out to a
1105 * Bam file.
1106 */
1107void GeomNode::CData::
1108write_datagram(BamWriter *manager, Datagram &dg) const {
1109 CPT(GeomList) geoms = _geoms.get_read_pointer();
1110 int num_geoms = geoms->size();
1111 nassertv(num_geoms == (int)(uint16_t)num_geoms);
1112 dg.add_uint16(num_geoms);
1113
1114 GeomList::const_iterator gi;
1115 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1116 const GeomEntry &entry = (*gi);
1117 manager->write_pointer(dg, entry._geom.get_read_pointer());
1118 manager->write_pointer(dg, entry._state);
1119 }
1120}
1121
1122/**
1123 * Receives an array of pointers, one for each time manager->read_pointer()
1124 * was called in fillin(). Returns the number of pointers processed.
1125 */
1126int GeomNode::CData::
1127complete_pointers(TypedWritable **p_list, BamReader *manager) {
1128 int pi = CycleData::complete_pointers(p_list, manager);
1129
1130 // Get the geom and state pointers.
1131 GeomList::iterator gi;
1132 PT(GeomList) geoms = _geoms.get_write_pointer();
1133 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1134 GeomEntry &entry = (*gi);
1135 entry._geom = DCAST(Geom, p_list[pi++]);
1136 entry._state = DCAST(RenderState, p_list[pi++]);
1137 }
1138
1139 return pi;
1140}
1141
1142/**
1143 * This internal function is called by make_from_bam to read in all of the
1144 * relevant data from the BamFile for the new GeomNode.
1145 */
1146void GeomNode::CData::
1147fillin(DatagramIterator &scan, BamReader *manager) {
1148 int num_geoms = scan.get_uint16();
1149 // Read the list of geoms and states. Push back a NULL for each one.
1150 PT(GeomList) geoms = new GeomList;
1151 geoms->reserve(num_geoms);
1152 for (int i = 0; i < num_geoms; i++) {
1153 manager->read_pointer(scan);
1154 manager->read_pointer(scan);
1155 geoms->push_back(GeomEntry(nullptr, nullptr));
1156 }
1157 _geoms = geoms;
1158}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
void collect(PandaNode *node, int attrib_types)
Collects the state and transform from the indicated node and adds it to the accumulator,...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
Definition: bamReader.cxx:808
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
Definition: bamReader.cxx:897
void set_aux_data(TypedWritable *obj, const std::string &name, AuxData *data)
Associates an arbitrary block of data with the indicated object (or NULL), and the indicated name.
Definition: bamReader.cxx:167
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
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Definition: bamReader.cxx:695
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_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
Definition: bamWriter.cxx:425
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
static BitMask< uint32_t, nbits > all_on()
Returns a BitMask whose bits are all on.
Definition: bitMask.I:32
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:29
This defines a bounding sphere, consisting of a center and a radius.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:27
Applies a scale to colors in the scene graph and on vertices.
This is a convenience class to specialize ConfigVariable as a boolean type.
This is similar to RefCountObj, but it implements a CopyOnWriteObject inheritance instead of a Refere...
Indicates which faces should be culled based on their vertex ordering.
get_effective_mode
Returns the effective culling mode.
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
Definition: cullHandler.cxx:43
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
The smallest atom of cull.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
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: cycleData.cxx:48
A class to retrieve the individual data elements previously stored in a Datagram.
uint16_t get_uint16()
Extracts an unsigned 16-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_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
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:50
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
void add_geoms_from(const GeomNode *other)
Copies the Geoms (and their associated RenderStates) from the indicated GeomNode into this one.
Definition: geomNode.cxx:615
void do_premunge(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer)
Uses the indicated GSG to premunge the Geoms in this node to optimize them for eventual rendering.
Definition: geomNode.cxx:874
void write_geoms(std::ostream &out, int indent_level) const
Writes a short description of all the Geoms in the node.
Definition: geomNode.cxx:793
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:594
virtual bool safe_to_combine() const
Returns true if it is generally safe to combine this particular kind of PandaNode with other kinds of...
Definition: geomNode.cxx:349
get_num_geoms
Returns the number of geoms in the node.
Definition: geomNode.h:71
Geoms get_geoms(Thread *current_thread=Thread::get_current_thread()) const
Returns an object that can be used to walk through the list of geoms of the node.
Definition: geomNode.I:177
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
Definition: geomNode.cxx:87
void unify(int max_indices, bool preserve_order)
Attempts to unify all of the Geoms contained within this node into a single Geom, or at least as few ...
Definition: geomNode.cxx:722
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this node by the indicated matrix, if it means anything to do so.
Definition: geomNode.cxx:321
virtual PandaNode * combine_with(PandaNode *other)
Collapses this node with the other node, if possible, and returns a pointer to the combined node,...
Definition: geomNode.cxx:446
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer)
Applies whatever attributes are specified in the AccumulatedAttribs object (and by the attrib_types b...
Definition: geomNode.cxx:101
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: geomNode.cxx:995
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of PandaNode by duplicating ...
Definition: geomNode.cxx:334
static void register_with_read_factory()
Tells the BamReader how to create objects of type GeomNode.
Definition: geomNode.cxx:986
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
virtual CollideMask get_legal_collide_mask() const
Returns the subset of CollideMask bits that may be set for this particular type of PandaNode.
Definition: geomNode.cxx:584
virtual bool is_geom_node() const
A simple downcast check.
Definition: geomNode.cxx:865
virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data)
Adds the node's contents to the CullResult we are building up during the cull traversal,...
void set_geom(int n, Geom *geom)
Replaces the nth Geom of the node with a new pointer.
Definition: geomNode.cxx:645
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread)
The recursive implementation of prepare_scene().
Definition: geomNode.cxx:362
void write_verbose(std::ostream &out, int indent_level) const
Writes a detailed description of all the Geoms in the node.
Definition: geomNode.cxx:809
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Definition: geomNode.cxx:1006
bool check_valid() const
Verifies that the each Geom within the GeomNode reference vertices that actually exist within its Geo...
Definition: geomNode.cxx:663
void decompose()
Calls decompose() on each Geom with the GeomNode.
Definition: geomNode.cxx:686
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
An object specifically designed to transform the vertices of a Geom without disturbing indexing or af...
bool apply_texture_colors(Geom *geom, TextureStage *ts, Texture *tex, const TexMatrixAttrib *tma, const LColor &base_color, bool keep_vertex_color)
Removes textures from Geoms by applying the texture colors to the vertices.
bool reverse_normals(Geom *geom)
Reverses the lighting normals on the vertex data, if any.
bool transform_colors(Geom *geom, const LVecBase4 &scale)
Transforms the colors in the indicated Geom by the indicated scale.
bool transform_vertices(Geom *geom, const LMatrix4 &mat)
Transforms the vertices and the normals in the indicated Geom by the indicated matrix.
bool set_color(Geom *geom, const LColor &color)
Overrides the color indicated within the Geom with the given replacement color.
bool remove_column(Geom *geom, const InternalName *column)
Removes the named column from the vertex data in the Geom.
bool transform_texcoords(Geom *geom, const InternalName *from_name, InternalName *to_name, const LMatrix4 &mat)
Transforms the texture coordinates in the indicated Geom by the indicated matrix.
void register_vertices(Geom *geom, bool might_have_unused)
Records the association of the Geom with its GeomVertexData, for the purpose of later removing unused...
This is the data for one array of a GeomVertexData structure.
This describes the structure of a single array within a Geom data.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This class defines the physical layout of the vertex data stored within a Geom.
A container for geometry primitives.
Definition: geom.h:54
bool check_valid() const
Verifies that the all of the primitives within the geom reference vertices that actually exist within...
Definition: geom.cxx:1074
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
virtual GeometricBoundingVolume * as_geometric_bounding_volume() final
Virtual downcast method.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
virtual PandaNode * combine_with(PandaNode *other)
Collapses this PandaNode with the other PandaNode, if possible, and returns a pointer to the combined...
Definition: pandaNode.cxx:319
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread)
The recursive implementation of prepare_scene().
Definition: pandaNode.cxx:2436
get_bounds_type
Returns the bounding volume type set with set_bounds_type().
Definition: pandaNode.h:293
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: pandaNode.cxx:3583
A table of objects that are saved within the graphics context for reference by handle later.
void enqueue_vertex_buffer(GeomVertexArrayData *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
void enqueue_texture(Texture *tex)
Indicates that a texture would like to be put on the list to be prepared when the GSG is next ready t...
void enqueue_index_buffer(GeomPrimitive *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
void enqueue_shader(Shader *shader)
Indicates that a shader would like to be put on the list to be prepared when the GSG is next ready to...
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 represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
Definition: shaderAttrib.I:71
Definition: shader.h:49
This is just a simple derivative of GeomMunger that adds the ability to munge states.
Definition: stateMunger.h:26
Applies a transform matrix to UV's before they are rendered.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:31
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
Definition: textureAttrib.h:55
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
Definition: textureAttrib.h:69
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
Definition: textureAttrib.h:55
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
get_texcoord_name
See set_texcoord_name.
Definition: textureStage.h:194
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
A thread; that is, a lightweight process.
Definition: thread.h:46
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
Indicates a coordinate-system transform on vertices.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
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.
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.
CPT(TransformState) GeomNode
This is used to support NodePath::calc_tight_bounds().
Definition: geomNode.cxx:469
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.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.