15 #include "config_pgraph.h" 16 #include "cullTraverser.h" 17 #include "cullTraverserData.h" 18 #include "transformState.h" 19 #include "renderState.h" 20 #include "colorAttrib.h" 21 #include "renderModeAttrib.h" 22 #include "cullFaceAttrib.h" 23 #include "depthOffsetAttrib.h" 24 #include "cullHandler.h" 27 #include "config_pgraph.h" 28 #include "boundingSphere.h" 29 #include "boundingBox.h" 30 #include "boundingHexahedron.h" 31 #include "portalClipper.h" 33 #include "geomTristrips.h" 34 #include "geomTriangles.h" 35 #include "geomLinestrips.h" 36 #include "geomLines.h" 37 #include "geomVertexWriter.h" 40 PStatCollector CullTraverser::_geom_nodes_pcollector(
"Nodes:GeomNodes");
42 PStatCollector CullTraverser::_geoms_occluded_pcollector(
"Geoms:Occluded");
54 _current_thread(
Thread::get_current_thread())
57 _has_tag_state_key =
false;
58 _initial_state = RenderState::make_empty();
61 _effective_incomplete_render =
true;
72 _current_thread(copy._current_thread),
73 _scene_setup(copy._scene_setup),
74 _camera_mask(copy._camera_mask),
75 _has_tag_state_key(copy._has_tag_state_key),
76 _tag_state_key(copy._tag_state_key),
77 _initial_state(copy._initial_state),
78 _view_frustum(copy._view_frustum),
79 _cull_handler(copy._cull_handler),
80 _portal_clipper(copy._portal_clipper),
81 _effective_incomplete_render(copy._effective_incomplete_render)
94 bool dr_incomplete_render) {
95 _scene_setup = scene_setup;
104 _has_tag_state_key = !_tag_state_key.empty();
107 _effective_incomplete_render = _gsg->get_incomplete_render() && dr_incomplete_render;
120 if (allow_portal_cull) {
128 bv->
is_of_type(GeometricBoundingVolume::get_class_type())) {
135 if (debug_portal_cull) {
143 _initial_state, _view_frustum,
149 if (debug_portal_cull) {
154 NodePath cull_center = _scene_setup->get_cull_center();
155 CPT(TransformState) transform = cull_center.
get_transform(root);
158 my_data._net_transform = my_data._net_transform->compose(transform);
163 _initial_state, _view_frustum,
191 _nodes_pcollector.add_level(1);
204 data._state = data._state->compose(get_depth_offset_state());
209 <<
"DecalEffect applied to " << *node <<
", not a GeomNode.\n";
221 while (i < num_children) {
223 do_traverse(next_data);
228 for (
int i = 0; i < num_children; i++) {
230 do_traverse(next_data);
255 const TransformState *internal_transform)
const {
256 PT(
Geom) bounds_viz = make_bounds_viz(vol);
258 if (bounds_viz != (
Geom *)NULL) {
259 _geoms_pcollector.add_level(2);
282 return data.is_in_view(_camera_mask);
294 CPT(TransformState) internal_transform = data.get_internal_transform(
this);
297 PT(
Geom) bounds_viz = make_tight_bounds_viz(node);
299 if (bounds_viz != (
Geom *)NULL) {
300 _geoms_pcollector.add_level(1);
312 internal_transform = internal_transform->compose(node->get_transform());
315 for (
int i = 0; i < num_geoms; ++i) {
329 PT(
Geom) CullTraverser::
335 }
else if (vol->
is_of_type(BoundingSphere::get_class_type())) {
338 static const int num_slices = 16;
339 static const int num_stacks = 8;
342 (
"bounds", GeomVertexFormat::get_v3(),
347 for (
int sl = 0; sl < num_slices; ++sl) {
348 PN_stdfloat longitude0 = (PN_stdfloat)sl / (PN_stdfloat)num_slices;
349 PN_stdfloat longitude1 = (PN_stdfloat)(sl + 1) / (PN_stdfloat)num_slices;
350 vertex.
add_data3(compute_point(sphere, 0.0, longitude0));
351 for (
int st = 1; st < num_stacks; ++st) {
352 PN_stdfloat latitude = (PN_stdfloat)st / (PN_stdfloat)num_stacks;
353 vertex.
add_data3(compute_point(sphere, latitude, longitude0));
354 vertex.
add_data3(compute_point(sphere, latitude, longitude1));
356 vertex.
add_data3(compute_point(sphere, 1.0, longitude0));
358 strip->add_next_vertices(num_stacks * 2);
359 strip->close_primitive();
362 geom =
new Geom(vdata);
363 geom->add_primitive(strip);
365 }
else if (vol->
is_of_type(BoundingHexahedron::get_class_type())) {
369 (
"bounds", GeomVertexFormat::get_v3(),
373 for (
int i = 0; i < 8; ++i ) {
378 lines->add_vertices(0, 1); lines->close_primitive();
379 lines->add_vertices(1, 2); lines->close_primitive();
380 lines->add_vertices(2, 3); lines->close_primitive();
381 lines->add_vertices(3, 0); lines->close_primitive();
383 lines->add_vertices(4, 5); lines->close_primitive();
384 lines->add_vertices(5, 6); lines->close_primitive();
385 lines->add_vertices(6, 7); lines->close_primitive();
386 lines->add_vertices(7, 4); lines->close_primitive();
388 lines->add_vertices(0, 4); lines->close_primitive();
389 lines->add_vertices(1, 5); lines->close_primitive();
390 lines->add_vertices(2, 6); lines->close_primitive();
391 lines->add_vertices(3, 7); lines->close_primitive();
393 geom =
new Geom(vdata);
394 geom->add_primitive(lines);
396 }
else if (vol->
is_of_type(FiniteBoundingVolume::get_class_type())) {
403 (
"bounds", GeomVertexFormat::get_v3(),
407 for (
int i = 0; i < 8; ++i ) {
412 tris->add_vertices(0, 4, 5);
413 tris->close_primitive();
414 tris->add_vertices(0, 5, 1);
415 tris->close_primitive();
416 tris->add_vertices(4, 6, 7);
417 tris->close_primitive();
418 tris->add_vertices(4, 7, 5);
419 tris->close_primitive();
420 tris->add_vertices(6, 2, 3);
421 tris->close_primitive();
422 tris->add_vertices(6, 3, 7);
423 tris->close_primitive();
424 tris->add_vertices(2, 0, 1);
425 tris->close_primitive();
426 tris->add_vertices(2, 1, 3);
427 tris->close_primitive();
428 tris->add_vertices(1, 5, 7);
429 tris->close_primitive();
430 tris->add_vertices(1, 7, 3);
431 tris->close_primitive();
432 tris->add_vertices(2, 6, 4);
433 tris->close_primitive();
434 tris->add_vertices(2, 4, 0);
435 tris->close_primitive();
437 geom =
new Geom(vdata);
438 geom->add_primitive(tris);
442 <<
"Don't know how to draw a representation of " 443 << vol->get_class_type() <<
"\n";
455 PT(
Geom) CullTraverser::
456 make_tight_bounds_viz(
PandaNode *node)
const {
462 bool found_any =
false;
463 node->calc_tight_bounds(n, x, found_any, TransformState::make_identity(),
467 (
"bounds", GeomVertexFormat::get_v3(),
485 strip->add_vertex(0);
486 strip->add_vertex(1);
487 strip->add_vertex(3);
488 strip->add_vertex(2);
489 strip->add_vertex(0);
490 strip->add_vertex(4);
491 strip->add_vertex(5);
492 strip->add_vertex(7);
493 strip->add_vertex(6);
494 strip->add_vertex(4);
495 strip->add_vertex(6);
496 strip->add_vertex(2);
497 strip->add_vertex(3);
498 strip->add_vertex(7);
499 strip->add_vertex(5);
500 strip->add_vertex(1);
501 strip->close_primitive();
503 geom =
new Geom(vdata);
504 geom->add_primitive(strip);
516 LVertex CullTraverser::
518 PN_stdfloat latitude, PN_stdfloat longitude) {
520 csincos(latitude * MathNumbers::pi, &s1, &c1);
523 csincos(longitude * 2.0 * MathNumbers::pi, &s2, &c2);
525 LVertex p(s1 * c2, s1 * s2, c1);
526 return p * sphere->get_radius() + sphere->get_center();
536 get_bounds_outer_viz_state() {
541 state = RenderState::make
542 (ColorAttrib::make_flat(
LColor(0.3, 1.0f, 0.5f, 1.0f)),
543 RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
544 CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise));
556 get_bounds_inner_viz_state() {
561 state = RenderState::make
562 (ColorAttrib::make_flat(
LColor(0.15f, 0.5f, 0.25f, 1.0f)),
563 RenderModeAttrib::make(RenderModeAttrib::M_wireframe),
564 CullFaceAttrib::make(CullFaceAttrib::M_cull_counter_clockwise));
576 get_depth_offset_state() {
581 state = RenderState::make
582 (DepthOffsetAttrib::make(1));
LPoint3 get_point(int n) const
Returns the nth vertex of the hexahedron.
int get_num_children() const
Returns the number of children of the node.
virtual int get_first_visible_child() const
Returns the index number of the first visible child of this node, or a number >= get_num_children() i...
A basic node of the scene graph or data graph.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void draw_camera_frustum()
Draw the current camera frustum in white color.
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
virtual void end_traverse()
Should be called when the traverser has finished traversing its scene, this gives it a chance to do a...
const RenderEffects * get_effects() const
Returns the complete RenderEffects that will be applied to this node.
virtual void traverse_below(CullTraverserData &data)
Traverses all the children of the indicated node, with the given data, which has been converted into ...
static BitMask< PN_uint32, nbits > all_on()
Returns a BitMask whose bits are all on.
bool is_empty() const
Any kind of volume might be empty.
DrawMask get_camera_mask() const
Returns the set of bits that represent the subset of the scene graph the camera will render...
This defines a bounding sphere, consisting of a center and a radius.
bool is_infinite() const
The other side of the empty coin is an infinite volume.
void draw_lines()
Draw all the lines in the buffer Cyan portal is the original geometry of the portal Yellow portal is ...
bool is_this_node_hidden(const DrawMask &camera_mask) const
Returns true if this particular node is hidden, even though we might be traversing past this node to ...
virtual bool has_selective_visibility() const
Should be overridden by derived classes to return true if this kind of node has some restrictions on ...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
Defines a series of triangle strips.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
int get_num_geoms() const
Returns the number of geoms in the node.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
PandaNode * node() const
Returns the node traversed to so far.
static NodePath any_path(PandaNode *node, Thread *current_thread=Thread::get_current_thread())
Returns a new NodePath that represents any arbitrary path from the root to the indicated node...
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
A lightweight class that represents a single element that may be timed and/or counted via stats...
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
void set_portal_clipper(PortalClipper *portal_clipper)
Specifies _portal_clipper object pointer that subsequent traverse() or traverse_below may use...
void release()
Releases the lock on this object.
This defines the abstract interface for an object that receives Geoms identified by the CullTraverser...
virtual void end_traverse()
This callback function is intended to be overridden by a derived class.
The smallest atom of cull.
const string & get_tag_state_key() const
Returns the tag key as set by a previous call to set_tag_state_key().
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
const RenderState * get_initial_state() const
Returns the initial state as set by a previous call to set_initial_state().
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
bool has_decal() const
This function is provided as an optimization, to speed up the render-time checking for the existance ...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
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, so that it will be drawn at render time.
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
Camera * get_camera_node() const
Returns the camera used to render the scene.
PandaNodePipelineReader * node_reader()
Returns the PipelineReader for the node traversed to so far.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Defines a series of disconnected line segments.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
A special kind of GeometricBoundingVolume that is known to be finite.
This is the base class for all three-component vectors and points.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
A thread; that is, a lightweight process.
Defines a series of line strips.
Encapsulates the data from a PandaNode, pre-fetched for one stage of the pipeline.
Defines a series of disconnected triangles.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
void draw_bounding_volume(const BoundingVolume *vol, const TransformState *internal_transform) const
Draws an appropriate visualization of the indicated bounding volume.
PandaNode * get_child(int n) const
Returns the nth child of the node.
TypeHandle is the identifier used to differentiate C++ class types.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
This object holds the camera position, etc., and other general setup information for rendering a part...
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
virtual bool is_geom_node() const
A simple downcast check.
virtual int get_next_visible_child(int n) const
Returns the index number of the next visible child of this node following the indicated child...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
This represents a unique collection of RenderEffect objects that correspond to a particular renderabl...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
virtual void set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsg, bool dr_incomplete_render)
Sets the SceneSetup object that indicates the initial camera position, etc.
A node that holds Geom objects, renderable pieces of geometry.
This defines a bounding convex hexahedron.