Panda3D
Loading...
Searching...
No Matches
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 pmap<InternalName *, pset<CPT(TransformState)> > name_transforms;
207
208 const TexMatrixAttrib *tma =
209 DCAST(TexMatrixAttrib, geom_attribs._tex_matrix);
210 int num_stages = tma->get_num_stages();
211 for (int i = 0; i < num_stages; i++) {
212 TextureStage *stage = tma->get_stage(i);
213 InternalName *name = stage->get_texcoord_name();
214 name_transforms[name].insert(tma->get_transform(stage)->get_unique());
215 }
216
217 if (geom_attribs._texture != nullptr) {
218 // There may be stages without a TexMatrixAttrib, which implicitly
219 // use the identity transform.
220 const TextureAttrib *ta = DCAST(TextureAttrib, geom_attribs._texture);
221 int num_on_stages = ta->get_num_on_stages();
222 for (int si = 0; si < num_on_stages; si++) {
223 TextureStage *stage = ta->get_on_stage(si);
224 InternalName *name = stage->get_texcoord_name();
225 if (!tma->has_stage(stage)) {
226 name_transforms[name].insert(TransformState::make_identity());
227 }
228 }
229 }
230
231 CPT(TexMatrixAttrib) new_tma = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
232
233 for (int i = 0; i < num_stages; i++) {
234 TextureStage *stage = tma->get_stage(i);
235 InternalName *name = stage->get_texcoord_name();
236 auto it = name_transforms.find(name);
237 if (it == name_transforms.end()) {
238 // Already processed this set.
239 }
240 else if (it->second.size() != 1) {
241 // We can't transform these texcoords, since the name is used by
242 // more than one active stage.
243 new_tma = DCAST(TexMatrixAttrib, new_tma->add_stage(stage, tma->get_transform(stage)));
244 }
245 else {
246 // It's safe to transform these texcoords; the name is used by
247 // no more than one active stage, or all these stages have the
248 // same transform.
249 const TransformState *transform = *(it->second.begin());
250 if (!transform->is_identity() &&
251 transformer.transform_texcoords(new_geom, name, name, transform->get_mat())) {
252 any_changed = true;
253 }
254 // Now make sure we don't transform this set more than once.
255 name_transforms.erase(it);
256 }
257 }
258
259 if (!new_tma->is_empty()) {
260 entry->_state = entry->_state->add_attrib(new_tma);
261 }
262 }
263 }
264
265 if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
266 entry->_state = geom_attribs._other->compose(entry->_state);
267 }
268
269 // We handle cull_face last, since that might involve duplicating the
270 // geom, and we'd also like to duplicate all of the changes we may have
271 // applied in the above.
272
273 if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
274 if (geom_attribs._cull_face != nullptr) {
275 const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, geom_attribs._cull_face);
276 CullFaceAttrib::Mode mode = cfa->get_effective_mode();
277 switch (mode) {
278 case CullFaceAttrib::M_cull_none:
279 // Doublesided polys. Duplicate them.
280 {
281 bool has_normals = (new_geom->get_vertex_data()->has_column(InternalName::get_normal()));
282 if (has_normals) {
283 // If the geometry has normals, we have to duplicate it to
284 // reverse the normals on the duplicate copy.
285 PT(Geom) dup_geom = new_geom->reverse();
286 transformer.reverse_normals(dup_geom);
287
288 geoms->push_back(GeomEntry(dup_geom, entry->_state));
289
290 // The above push_back() operation might have invalidated our
291 // old pointer into the list, so we reassign it now.
292 entry = &(*geoms)[i];
293
294 } else {
295 // If there are no normals, we can just doubleside it in
296 // place. This is preferable because we can share vertices.
297 new_geom->doubleside_in_place();
298 any_changed = true;
299 }
300 }
301 break;
302
303 case CullFaceAttrib::M_cull_counter_clockwise:
304 // Reverse winding order.
305 new_geom->reverse_in_place();
306 transformer.reverse_normals(new_geom);
307 any_changed = true;
308 break;
309
310 default:
311 break;
312 }
313 }
314 }
315
316 if (any_changed) {
317 entry->_geom = new_geom;
318 }
319 }
320 }
321 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
322
323 if ((attrib_types & SceneGraphReducer::TT_apply_texture_color) != 0) {
324 transformer.apply_texture_colors(this, attribs._other);
325 }
326
327 transformer.register_vertices(this, false);
328}
329
330/**
331 * Transforms the contents of this node by the indicated matrix, if it means
332 * anything to do so. For most kinds of nodes, this does nothing.
333 *
334 * For a GeomNode, this does the right thing, but it is better to use a
335 * GeomTransformer instead, since it will share the new arrays properly
336 * between different GeomNodes.
337 */
339xform(const LMatrix4 &mat) {
340 GeomTransformer transformer;
341 transformer.transform_vertices(this, mat);
342}
343
344
345/**
346 * Returns true if it is generally safe to flatten out this particular kind of
347 * PandaNode by duplicating instances (by calling dupe_for_flatten()), false
348 * otherwise (for instance, a Camera cannot be safely flattened, because the
349 * Camera pointer itself is meaningful).
350 */
352safe_to_flatten() const {
353 if (_preserved) {
354 return false;
355 }
356
357 return true;
358}
359
360/**
361 * Returns true if it is generally safe to combine this particular kind of
362 * PandaNode with other kinds of PandaNodes of compatible type, adding
363 * children or whatever. For instance, an LODNode should not be combined with
364 * any other PandaNode, because its set of children is meaningful.
365 */
367safe_to_combine() const {
368 if (_preserved) {
369 return false;
370 }
371
372 return true;
373}
374
375/**
376 * The recursive implementation of prepare_scene(). Don't call this directly;
377 * call PandaNode::prepare_scene() or NodePath::prepare_scene() instead.
378 */
381 GeomTransformer &transformer, Thread *current_thread) {
382 PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects();
383
384 CDReader cdata(_cycler, current_thread);
385 GeomList::const_iterator gi;
386 CPT(GeomList) geoms = cdata->get_geoms();
387 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
388 const GeomEntry &entry = (*gi);
389 CPT(RenderState) geom_state = node_state->compose(entry._state);
390 CPT(Geom) geom = entry._geom.get_read_pointer();
391
392 // Munge the geom as required by the GSG.
393 PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
394 geom = transformer.premunge_geom(geom, munger);
395
396 // Prepare each of the vertex arrays in the munged Geom.
397 CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(false, current_thread);
398 GeomVertexDataPipelineReader vdata_reader(vdata, current_thread);
399 int num_arrays = vdata_reader.get_num_arrays();
400 for (int i = 0; i < num_arrays; ++i) {
401 CPT(GeomVertexArrayData) array = vdata_reader.get_array(i);
402 prepared_objects->enqueue_vertex_buffer((GeomVertexArrayData *)array.p());
403 }
404
405 // And also each of the index arrays.
406 int num_primitives = geom->get_num_primitives();
407 for (int i = 0; i < num_primitives; ++i) {
408 CPT(GeomPrimitive) prim = geom->get_primitive(i);
409 prepared_objects->enqueue_index_buffer((GeomPrimitive *)prim.p());
410 }
411
412 if (munger->is_of_type(StateMunger::get_class_type())) {
413 StateMunger *state_munger = (StateMunger *)munger.p();
414 geom_state = state_munger->munge_state(geom_state);
415 }
416
417 // As well as the shaders.
418 const ShaderAttrib *sa;
419 if (geom_state->get_attrib(sa)) {
420 Shader *shader = (Shader *)sa->get_shader();
421 if (shader != nullptr) {
422 prepared_objects->enqueue_shader(shader);
423 }
424 else if (sa->auto_shader()) {
425 gsg->ensure_generated_shader(geom_state);
426 }
427 else if (munger->is_of_type(StateMunger::get_class_type())) {
428 // Premunge the state for the fixed-function pipeline.
429 StateMunger *state_munger = (StateMunger *)munger.p();
430 geom_state = state_munger->munge_state(geom_state);
431 }
432 // TODO: prepare the shader inputs.
433 }
434
435 // And now prepare each of the textures.
436 const TextureAttrib *ta;
437 if (geom_state->get_attrib(ta)) {
438 int num_stages = ta->get_num_on_stages();
439 for (int i = 0; i < num_stages; ++i) {
440 Texture *texture = ta->get_on_texture(ta->get_on_stage(i));
441 // TODO: prepare the sampler states, if specified.
442 if (texture != nullptr) {
443 prepared_objects->enqueue_texture(texture);
444 }
445 }
446 }
447 }
448
449 PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
450}
451
452
453/**
454 * Collapses this node with the other node, if possible, and returns a pointer
455 * to the combined node, or NULL if the two nodes cannot safely be combined.
456 *
457 * The return value may be this, other, or a new node altogether.
458 *
459 * This function is called from GraphReducer::flatten(), and need not deal
460 * with children; its job is just to decide whether to collapse the two nodes
461 * and what the collapsed node should look like.
462 */
464combine_with(PandaNode *other) {
465 if (is_exact_type(get_class_type()) &&
466 other->is_exact_type(get_class_type())) {
467 // Two GeomNodes can combine by moving Geoms from one to the other.
468 GeomNode *gother = DCAST(GeomNode, other);
469 add_geoms_from(gother);
470 return this;
471 }
472
473 return PandaNode::combine_with(other);
474}
475
476/**
477 * This is used to support NodePath::calc_tight_bounds(). It is not intended
478 * to be called directly, and it has nothing to do with the normal Panda
479 * bounding-volume computation.
480 *
481 * If the node contains any geometry, this updates min_point and max_point to
482 * enclose its bounding box. found_any is to be set true if the node has any
483 * geometry at all, or left alone if it has none. This method may be called
484 * over several nodes, so it may enter with min_point, max_point, and
485 * found_any already set.
486 */
487CPT(TransformState) GeomNode::
488calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
489 const TransformState *transform, Thread *current_thread) const {
490 CPT(TransformState) next_transform =
491 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
492 current_thread);
493
494 const LMatrix4 &mat = next_transform->get_mat();
495
496 CDReader cdata(_cycler, current_thread);
497 GeomList::const_iterator gi;
498 CPT(GeomList) geoms = cdata->get_geoms();
499 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
500 CPT(Geom) geom = (*gi)._geom.get_read_pointer();
501 geom->calc_tight_bounds(min_point, max_point, found_any,
502 geom->get_animated_vertex_data(true, current_thread),
503 !next_transform->is_identity(), mat,
504 current_thread);
505 }
506
507 return next_transform;
508}
509
510/**
511 * Returns true if there is some value to visiting this particular node during
512 * the cull traversal for any camera, false otherwise. This will be used to
513 * optimize the result of get_net_draw_show_mask(), so that any subtrees that
514 * contain only nodes for which is_renderable() is false need not be visited.
515 */
516bool GeomNode::
517is_renderable() const {
518 return true;
519}
520
521/**
522 * Adds the node's contents to the CullResult we are building up during the
523 * cull traversal, so that it will be drawn at render time. For most nodes
524 * other than GeomNodes, this is a do-nothing operation.
525 */
526void GeomNode::
528 trav->_geom_nodes_pcollector.add_level(1);
529
530 if (pgraph_cat.is_spam()) {
531 pgraph_cat.spam()
532 << "Found " << *this << " in state " << *data._state
533 << " draw_mask = " << data._draw_mask << "\n";
534 }
535
536 Thread *current_thread = trav->get_current_thread();
537
538 // Get all the Geoms, with no decalling.
539 Geoms geoms = get_geoms(current_thread);
540 int num_geoms = geoms.get_num_geoms();
541 trav->_geoms_pcollector.add_level(num_geoms);
542 CPT(TransformState) internal_transform = data.get_internal_transform(trav);
543
544 for (int i = 0; i < num_geoms; i++) {
545 CPT(Geom) geom = geoms.get_geom(i);
546 if (geom->is_empty()) {
547 continue;
548 }
549
550 CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
551 if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
552 // Cull.
553 continue;
554 }
555
556 // Cull the Geom bounding volume against the view frustum andor the cull
557 // planes. Don't bother unless we've got more than one Geom, since
558 // otherwise the bounding volume of the GeomNode is (probably) the same as
559 // that of the one Geom, and we've already culled against that.
560 if (num_geoms > 1) {
561 if (data._view_frustum != nullptr) {
562 // Cull the individual Geom against the view frustum.
563 CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
564 const GeometricBoundingVolume *geom_gbv =
565 geom_volume->as_geometric_bounding_volume();
566
567 int result = data._view_frustum->contains(geom_gbv);
568 if (result == BoundingVolume::IF_no_intersection) {
569 // Cull this Geom.
570 continue;
571 }
572 }
573 if (!data._cull_planes->is_empty()) {
574 // Also cull the Geom against the cull planes.
575 CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
576 const GeometricBoundingVolume *geom_gbv =
577 geom_volume->as_geometric_bounding_volume();
578 int result;
579 data._cull_planes->do_cull(result, state, geom_gbv);
580 if (result == BoundingVolume::IF_no_intersection) {
581 // Cull.
582 continue;
583 }
584 }
585 }
586
587 CullableObject *object =
588 new CullableObject(std::move(geom), std::move(state), internal_transform);
589 trav->get_cull_handler()->record_object(object, trav);
590 }
591}
592
593/**
594 * Returns the subset of CollideMask bits that may be set for this particular
595 * type of PandaNode. For most nodes, this is 0; it doesn't make sense to set
596 * a CollideMask for most kinds of nodes.
597 *
598 * For nodes that can be collided with, such as GeomNode and CollisionNode,
599 * this returns all bits on.
600 */
605
606/**
607 * Adds a new Geom to the node. The geom is given the indicated state (which
608 * may be RenderState::make_empty(), to completely inherit its state from the
609 * scene graph).
610 */
612add_geom(Geom *geom, const RenderState *state) {
613 nassertv(geom != nullptr);
614 nassertv(geom->check_valid());
615 nassertv(state != nullptr);
616
617 Thread *current_thread = Thread::get_current_thread();
618 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
619 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
620
621 cdata->modify_geoms()->push_back(GeomEntry(geom, state));
622 }
623 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
624
625 mark_internal_bounds_stale();
626}
627
628/**
629 * Copies the Geoms (and their associated RenderStates) from the indicated
630 * GeomNode into this one.
631 */
633add_geoms_from(const GeomNode *other) {
634 Thread *current_thread = Thread::get_current_thread();
635 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
636 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
637 CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
638
639 GeomList::const_iterator gi;
640 CPT(GeomList) other_geoms = cdata_other->get_geoms();
641 PT(GeomList) this_geoms = cdata->modify_geoms();
642 for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) {
643 const GeomEntry &entry = (*gi);
644 nassertv(entry._geom.get_read_pointer()->check_valid());
645 this_geoms->push_back(entry);
646 }
647 }
648 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
649
650 mark_internal_bounds_stale();
651}
652
653/**
654 * Replaces the nth Geom of the node with a new pointer. There must already
655 * be a Geom in this slot.
656 *
657 * Note that if this method is called in a downstream stage (for instance,
658 * during cull or draw), then it will propagate the new list of Geoms upstream
659 * all the way to pipeline stage 0, which may step on changes that were made
660 * independently in pipeline stage 0. Use with caution.
661 */
663set_geom(int n, Geom *geom) {
664 nassertv(geom != nullptr);
665 nassertv(geom->check_valid());
666
667 CDWriter cdata(_cycler, true);
668 PT(GeomList) geoms = cdata->modify_geoms();
669 nassertv(n >= 0 && n < (int)geoms->size());
670 (*geoms)[n]._geom = geom;
671
672 mark_internal_bounds_stale();
673}
674
675/**
676 * Verifies that the each Geom within the GeomNode reference vertices that
677 * actually exist within its GeomVertexData. Returns true if the GeomNode
678 * appears to be valid, false otherwise.
679 */
681check_valid() const {
682 int num_geoms = get_num_geoms();
683 for (int i = 0; i < num_geoms; i++) {
684 const Geom *geom = get_geom(i);
685 if (!geom->check_valid()) {
686 return false;
687 }
688 }
689
690 return true;
691}
692
693/**
694 * Calls decompose() on each Geom with the GeomNode. This decomposes higher-
695 * order primitive types, like triangle strips, into lower-order types like
696 * indexed triangles. Normally there is no reason to do this, but it can be
697 * useful as an early preprocessing step, to allow a later call to unify() to
698 * proceed more quickly.
699 *
700 * See also SceneGraphReducer::decompose(), which is the normal way this is
701 * called.
702 */
704decompose() {
705 Thread *current_thread = Thread::get_current_thread();
706 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
707 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
708
709 GeomList::iterator gi;
710 PT(GeomList) geoms = cdata->modify_geoms();
711 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
712 GeomEntry &entry = (*gi);
713 nassertv(entry._geom.test_ref_count_integrity());
714 PT(Geom) geom = entry._geom.get_write_pointer();
715 geom->decompose_in_place();
716 }
717 }
718 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
719}
720
721/**
722 * Attempts to unify all of the Geoms contained within this node into a single
723 * Geom, or at least as few Geoms as possible. In turn, the individual
724 * GeomPrimitives contained within each resulting Geom are also unified. The
725 * goal is to reduce the number of GeomPrimitives within the node as far as
726 * possible. This may result in composite primitives, such as triangle strips
727 * and triangle fans, being decomposed into triangles. See also
728 * Geom::unify().
729 *
730 * max_indices represents the maximum number of indices that will be put in
731 * any one GeomPrimitive. If preserve_order is true, then the primitives will
732 * not be reordered during the operation, even if this results in a suboptimal
733 * result.
734 *
735 * In order for this to be successful, the primitives must reference the same
736 * GeomVertexData, have the same fundamental primitive type, and have
737 * compatible shade models.
738 */
740unify(int max_indices, bool preserve_order) {
741 bool any_changed = false;
742
743 Thread *current_thread = Thread::get_current_thread();
744 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
745 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
746
747 PT(GeomList) new_geoms = new GeomList;
748
749 // Try to unify each Geom with each preceding Geom. This is an n^2
750 // operation, but usually there are only a handful of Geoms to consider,
751 // so that's not a big deal.
752 GeomList::const_iterator gi;
753 CPT(GeomList) old_geoms = cdata->get_geoms();
754 for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) {
755 const GeomEntry &old_entry = (*gi);
756
757 bool unified = false;
758
759 // Go from back to front, to minimize damage to the primitive ordering.
760 GeomList::reverse_iterator gj;
761 for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) {
762 GeomEntry &new_entry = (*gj);
763 if (old_entry._state == new_entry._state) {
764 // Both states match, so try to combine the primitives.
765 CPT(Geom) old_geom = old_entry._geom.get_read_pointer();
766 PT(Geom) new_geom = new_entry._geom.get_write_pointer();
767 if (new_geom->copy_primitives_from(old_geom)) {
768 // Successfully combined!
769 unified = true;
770 any_changed = true;
771 }
772 }
773
774 if (preserve_order) {
775 // If we're insisting on preserving the order, we can only attempt
776 // to merge with the tail of the list.
777 break;
778 }
779 }
780
781 if (!unified) {
782 // Couldn't unify this Geom with anything, so just add it to the
783 // output list.
784 new_geoms->push_back(old_entry);
785 }
786 }
787
788 // Done! We'll keep whatever's left in the output list.
789 cdata->set_geoms(new_geoms);
790
791 // Finally, go back through and unify the resulting geom(s).
792 GeomList::iterator wgi;
793 for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) {
794 GeomEntry &entry = (*wgi);
795 nassertv(entry._geom.test_ref_count_integrity());
796 PT(Geom) geom = entry._geom.get_write_pointer();
797 geom->unify_in_place(max_indices, preserve_order);
798 }
799 }
800 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
801
802 if (any_changed) {
803 mark_internal_bounds_stale();
804 }
805}
806
807/**
808 * Writes a short description of all the Geoms in the node.
809 */
811write_geoms(std::ostream &out, int indent_level) const {
812 CDReader cdata(_cycler);
813 write(out, indent_level);
814 GeomList::const_iterator gi;
815 CPT(GeomList) geoms = cdata->get_geoms();
816 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
817 const GeomEntry &entry = (*gi);
818 indent(out, indent_level + 2)
819 << *entry._geom.get_read_pointer() << " " << *entry._state << "\n";
820 }
821}
822
823/**
824 * Writes a detailed description of all the Geoms in the node.
825 */
827write_verbose(std::ostream &out, int indent_level) const {
828 CDReader cdata(_cycler);
829 write(out, indent_level);
830 GeomList::const_iterator gi;
831 CPT(GeomList) geoms = cdata->get_geoms();
832 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
833 const GeomEntry &entry = (*gi);
834 CPT(Geom) geom = entry._geom.get_read_pointer();
835 indent(out, indent_level + 2)
836 << *geom << " " << *entry._state << "\n";
837 geom->write(out, indent_level + 4);
838 }
839}
840
841/**
842 *
843 */
844void GeomNode::
845output(std::ostream &out) const {
846 // Accumulate the total set of RenderAttrib types that are applied to any of
847 // our Geoms, so we can output them too. The result will be the list of
848 // attrib types that might be applied to some Geoms, but not necessarily to
849 // all Geoms.
850
851 CDReader cdata(_cycler);
852
853 pset<TypeHandle> attrib_types;
854
855 GeomList::const_iterator gi;
856 CPT(RenderState) common = RenderState::make_empty();
857
858 CPT(GeomList) geoms = cdata->get_geoms();
859 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
860 const GeomEntry &entry = (*gi);
861 common = common->compose(entry._state);
862 }
863
864 PandaNode::output(out);
865 out << " (" << geoms->size() << " geoms";
866
867 if (!common->is_empty()) {
868 out << ": " << *common;
869 }
870
871 out << ")";
872}
873
874/**
875 * A simple downcast check. Returns true if this kind of node happens to
876 * inherit from GeomNode, false otherwise.
877 *
878 * This is provided as a a faster alternative to calling
879 * is_of_type(GeomNode::get_class_type()), since this test is so important to
880 * rendering.
881 */
883is_geom_node() const {
884 return true;
885}
886
887/**
888 * Uses the indicated GSG to premunge the Geoms in this node to optimize them
889 * for eventual rendering. See SceneGraphReducer::premunge().
890 */
893 const RenderState *node_state,
894 GeomTransformer &transformer) {
895 Thread *current_thread = Thread::get_current_thread();
896
897 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
898 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
899
900 GeomList::iterator gi;
901 PT(GeomList) geoms = cdata->modify_geoms();
902 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
903 GeomEntry &entry = (*gi);
904 CPT(RenderState) geom_state = node_state->compose(entry._state);
905 CPT(Geom) geom = entry._geom.get_read_pointer();
906 PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
907 entry._geom = transformer.premunge_geom(geom, munger);
908 }
909 }
910 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
911}
912
913/**
914 * Recursively calls Geom::mark_bounds_stale() on every Geom at this node and
915 * below.
916 */
917void GeomNode::
918r_mark_geom_bounds_stale(Thread *current_thread) {
919 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
920 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
921
922 GeomList::iterator gi;
923 PT(GeomList) geoms = cdata->modify_geoms();
924 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
925 GeomEntry &entry = (*gi);
926 entry._geom.get_read_pointer()->mark_bounds_stale();
927 }
928 }
929 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
930 mark_internal_bounds_stale();
931
932 PandaNode::r_mark_geom_bounds_stale(current_thread);
933}
934
935/**
936 * Returns a newly-allocated BoundingVolume that represents the internal
937 * contents of the node. Should be overridden by PandaNode classes that
938 * contain something internally.
939 */
940void GeomNode::
941compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
942 int &internal_vertices,
943 int pipeline_stage,
944 Thread *current_thread) const {
945 int num_vertices = 0;
946
947 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
948
950 pvector<CPT(BoundingVolume) > child_volumes_ref;
951 bool all_box = true;
952
953 GeomList::const_iterator gi;
954 CPT(GeomList) geoms = cdata->get_geoms();
955 child_volumes.reserve(geoms->size());
956 child_volumes_ref.reserve(geoms->size());
957
958 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
959 const GeomEntry &entry = (*gi);
960 CPT(Geom) geom = entry._geom.get_read_pointer();
961 CPT(BoundingVolume) volume = geom->get_bounds();
962
963 if (!volume->is_empty()) {
964 child_volumes.push_back(volume);
965 child_volumes_ref.push_back(volume);
966 if (!volume->is_exact_type(BoundingBox::get_class_type())) {
967 all_box = false;
968 }
969 }
970 num_vertices += geom->get_nested_vertices();
971 }
972
974
975 BoundingVolume::BoundsType btype = get_bounds_type();
976 if (btype == BoundingVolume::BT_default) {
977 btype = bounds_type;
978 }
979
980 if (btype == BoundingVolume::BT_box ||
981 (btype != BoundingVolume::BT_sphere && all_box)) {
982 // If all of the child volumes are a BoundingBox, then our volume is also
983 // a BoundingBox.
984 gbv = new BoundingBox;
985 } else {
986 // Otherwise, it's a sphere.
987 gbv = new BoundingSphere;
988 }
989
990 if (child_volumes.size() > 0) {
991 const BoundingVolume **child_begin = &child_volumes[0];
992 const BoundingVolume **child_end = child_begin + child_volumes.size();
993 ((BoundingVolume *)gbv)->around(child_begin, child_end);
994 }
995
996 internal_bounds = gbv;
997 internal_vertices = num_vertices;
998}
999
1000/**
1001 * Tells the BamReader how to create objects of type GeomNode.
1002 */
1005 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
1006}
1007
1008/**
1009 * Writes the contents of this object to the datagram for shipping out to a
1010 * Bam file.
1011 */
1013write_datagram(BamWriter *manager, Datagram &dg) {
1014 PandaNode::write_datagram(manager, dg);
1015 manager->write_cdata(dg, _cycler);
1016}
1017
1018/**
1019 * Called by the BamReader to perform any final actions needed for setting up
1020 * the object after all objects have been read and all pointers have been
1021 * completed.
1022 */
1024finalize(BamReader *manager) {
1025 if (manager->get_file_minor_ver() < 14) {
1026 // With version 6.14, we changed the default ColorAttrib behavior from
1027 // make_vertex() to make_flat(). This means that every Geom that contains
1028 // vertex colors now needs to have an explicit ColorAttrib::make_vertex()
1029 // on its state.
1030
1031 // Since we shouldn't override a different ColorAttrib inherited from
1032 // above, we create this new attrib with an override of -1.
1033
1034 CPT(InternalName) color = InternalName::get_color();
1035 CPT(RenderAttrib) vertex_color = ColorAttrib::make_vertex();
1036
1037 Thread *current_thread = Thread::get_current_thread();
1038 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
1039 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
1040
1041 GeomList::iterator gi;
1042 PT(GeomList) geoms = cdata->modify_geoms();
1043 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1044 GeomEntry &entry = (*gi);
1045 CPT(Geom) geom = entry._geom.get_read_pointer();
1046
1047 // Force the various GeomVertexArrayFormat objects to finalize
1048 // themselves. We have to do this before we can reliably call
1049 // GeomVertexData::has_column().
1050 CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
1051 CPT(GeomVertexFormat) vformat = vdata->get_format();
1052 for (size_t i = 0; i < vformat->get_num_arrays(); ++i) {
1053 const GeomVertexArrayFormat *varray = vformat->get_array(i);
1054 manager->finalize_now((GeomVertexArrayFormat *)varray);
1055 }
1056
1057 if (vdata->has_column(color) &&
1058 !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
1059 // We'll be reassigning the RenderState. Therefore, save it
1060 // temporarily to increment its reference count.
1061 PT(BamAuxData) aux_data = new BamAuxData;
1062 aux_data->_hold_state = entry._state;
1063 manager->set_aux_data((RenderState *)entry._state.p(), "hold_state", aux_data);
1064
1065 entry._state = entry._state->add_attrib(vertex_color, -1);
1066 }
1067 }
1068 }
1069 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
1070 }
1071}
1072
1073/**
1074 * This function is called by the BamReader's factory when a new object of
1075 * type GeomNode is encountered in the Bam file. It should create the
1076 * GeomNode and extract its information from the file.
1077 */
1078TypedWritable *GeomNode::
1079make_from_bam(const FactoryParams &params) {
1080 GeomNode *node = new GeomNode("");
1081 DatagramIterator scan;
1082 BamReader *manager;
1083
1084 parse_params(params, scan, manager);
1085 node->fillin(scan, manager);
1086
1087 if (manager->get_file_minor_ver() < 14) {
1088 manager->register_finalize(node);
1089 }
1090
1091 return node;
1092}
1093
1094/**
1095 * This internal function is called by make_from_bam to read in all of the
1096 * relevant data from the BamFile for the new GeomNode.
1097 */
1098void GeomNode::
1099fillin(DatagramIterator &scan, BamReader *manager) {
1100 PandaNode::fillin(scan, manager);
1101 manager->read_cdata(scan, _cycler);
1102}
1103
1104/**
1105 *
1106 */
1107GeomNode::CData::
1108CData(const GeomNode::CData &copy) :
1109 _geoms(copy._geoms)
1110{
1111}
1112
1113/**
1114 *
1115 */
1116CycleData *GeomNode::CData::
1117make_copy() const {
1118 return new CData(*this);
1119}
1120
1121/**
1122 * Writes the contents of this object to the datagram for shipping out to a
1123 * Bam file.
1124 */
1125void GeomNode::CData::
1126write_datagram(BamWriter *manager, Datagram &dg) const {
1127 CPT(GeomList) geoms = _geoms.get_read_pointer();
1128 int num_geoms = geoms->size();
1129 nassertv(num_geoms == (int)(uint16_t)num_geoms);
1130 dg.add_uint16(num_geoms);
1131
1132 GeomList::const_iterator gi;
1133 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1134 const GeomEntry &entry = (*gi);
1135 manager->write_pointer(dg, entry._geom.get_read_pointer());
1136 manager->write_pointer(dg, entry._state);
1137 }
1138}
1139
1140/**
1141 * Receives an array of pointers, one for each time manager->read_pointer()
1142 * was called in fillin(). Returns the number of pointers processed.
1143 */
1144int GeomNode::CData::
1145complete_pointers(TypedWritable **p_list, BamReader *manager) {
1146 int pi = CycleData::complete_pointers(p_list, manager);
1147
1148 // Get the geom and state pointers.
1149 GeomList::iterator gi;
1150 PT(GeomList) geoms = _geoms.get_write_pointer();
1151 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1152 GeomEntry &entry = (*gi);
1153 entry._geom = DCAST(Geom, p_list[pi++]);
1154 entry._state = DCAST(RenderState, p_list[pi++]);
1155 }
1156
1157 return pi;
1158}
1159
1160/**
1161 * This internal function is called by make_from_bam to read in all of the
1162 * relevant data from the BamFile for the new GeomNode.
1163 */
1164void GeomNode::CData::
1165fillin(DatagramIterator &scan, BamReader *manager) {
1166 int num_geoms = scan.get_uint16();
1167 // Read the list of geoms and states. Push back a NULL for each one.
1168 PT(GeomList) geoms = new GeomList;
1169 geoms->reserve(num_geoms);
1170 for (int i = 0; i < num_geoms; i++) {
1171 manager->read_pointer(scan);
1172 manager->read_pointer(scan);
1173 geoms->push_back(GeomEntry(nullptr, nullptr));
1174 }
1175 _geoms = geoms;
1176}
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...
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
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.
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
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
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.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
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.
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,...
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.
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...
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:633
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:892
void write_geoms(std::ostream &out, int indent_level) const
Writes a short description of all the Geoms in the node.
Definition geomNode.cxx:811
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition geomNode.cxx:612
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:367
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:740
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:339
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:464
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.
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:352
static void register_with_read_factory()
Tells the BamReader how to create objects of type GeomNode.
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:602
virtual bool is_geom_node() const
A simple downcast check.
Definition geomNode.cxx:883
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:663
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:380
void write_verbose(std::ostream &out, int indent_level) const
Writes a detailed description of all the Geoms in the node.
Definition geomNode.cxx:827
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
bool check_valid() const
Verifies that the each Geom within the GeomNode reference vertices that actually exist within its Geo...
Definition geomNode.cxx:681
void decompose()
Calls decompose() on each Geom with the GeomNode.
Definition geomNode.cxx:704
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
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.
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...
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread)
The recursive implementation of prepare_scene().
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.
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...
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...
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...
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
Defines the properties of a named stage of the multitexture pipeline.
get_texcoord_name
See set_texcoord_name.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition texture.h:72
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.
get_mat
Returns the matrix that describes the transform.
bool is_identity() const
Returns true if the transform represents the identity matrix, false otherwise.
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.
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.
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.