diff --git a/panda/src/pgraph/portalClipper.I b/panda/src/pgraph/portalClipper.I index 955d182179..a7601a892c 100755 --- a/panda/src/pgraph/portalClipper.I +++ b/panda/src/pgraph/portalClipper.I @@ -101,24 +101,43 @@ draw_camera_frustum() { } //////////////////////////////////////////////////////////////////// -// Function: PortalClipper::set_reduced_frustum +// Function: PortalClipper::set_view_frustum // Access: Public -// Description: set the current reduced frustum before traversing +// Description: set the current view frustum before traversing // //////////////////////////////////////////////////////////////////// INLINE void PortalClipper:: -set_reduced_frustum(BoundingHexahedron *frustum) { - _reduced_frustum = frustum; +set_view_frustum(BoundingHexahedron *frustum) { + _view_frustum = frustum; } + //////////////////////////////////////////////////////////////////// -// Function: PortalClipper::is_in_view +// Function: PortalClipper::is_facing_view +// Access: Public +// Description: checks if the portal plane (in camera space) +// is facing the camera's near plane +//////////////////////////////////////////////////////////////////// +INLINE bool PortalClipper:: +is_facing_view(Planef portal_plane) +{ + Planef view_plane(_view_frustum->get_point(4), _view_frustum->get_point(5), _view_frustum->get_point(6)); + + // use the view_frustum's near plane to calculate direction + pgraph_cat.debug() << portal_plane.get_normal() << "; " << -view_plane.get_normal() << endl; + float direction = portal_plane.get_normal().dot(-view_plane.get_normal()); + pgraph_cat.debug() << "Found direction of " << direction << endl; + return (direction < _FACING_THRESHOLD); +} + +//////////////////////////////////////////////////////////////////// +// Function: PortalClipper::is_whole_portal_in_view // Access: Public // Description: checks if portal_node is within the view frustum. // If so, then the portal is worth considering. This // is a 1st level test to weed out most of the portals //////////////////////////////////////////////////////////////////// INLINE bool PortalClipper:: -is_in_view(const NodePath &node_path) { +is_whole_portal_in_view(const NodePath &node_path) { const BoundingVolume *bv = &_portal_node->get_bound(); @@ -130,27 +149,28 @@ is_in_view(const NodePath &node_path) { CPT(TransformState) ctransform = node_path.get_transform(_scene_setup->get_cull_center()); gbv->xform(ctransform->get_mat()); - int result = _reduced_frustum->contains(gbv); - pgraph_cat.debug() << "1st level test if portal is in view " << result << endl; + int result = _view_frustum->contains(gbv); + + pgraph_cat.debug() << "1st level test if portal: " << *_view_frustum << " is in view " << result << endl; return (result != 0); } //////////////////////////////////////////////////////////////////// -// Function: PortalClipper::facing_camera +// Function: PortalClipper::is_partial_portal_in_view // Access: Public // Description: checks if any of the _coords is within the view frustum. // If so, then the portal is facing the camera. 2nd level // test to make sure this portal is worth visiting //////////////////////////////////////////////////////////////////// INLINE bool PortalClipper:: -is_facing_camera(const NodePath &node_path) { +is_partial_portal_in_view(const NodePath &node_path) { int result = 0; - // check if the camera_center to portal_center lineseg is in view + // check if any of the _coords in tested frustum for (int j=0; j<_num_vert; ++j) { - result |= _reduced_frustum->contains(_coords[j]); + result |= _view_frustum->contains(_coords[j]); } - pgraph_cat.debug() << "frustum->contains(coord) result = " << result << endl; + pgraph_cat.debug() << "frustum: " << *_view_frustum << " contains(coord) result = " << result << endl; return (result != 0); } diff --git a/panda/src/pgraph/portalClipper.cxx b/panda/src/pgraph/portalClipper.cxx index 3f031b0d66..2ee4a940e5 100755 --- a/panda/src/pgraph/portalClipper.cxx +++ b/panda/src/pgraph/portalClipper.cxx @@ -47,7 +47,7 @@ PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup) { _geom_point = new GeomPoint; _geom_linestrip = new GeomLinestrip; - _view_frustum = _reduced_frustum = DCAST(BoundingHexahedron, frustum); + _view_frustum = DCAST(BoundingHexahedron, frustum); _scene_setup = scene_setup; } @@ -260,6 +260,10 @@ prepare_portal(const NodePath &node_path) temp[2] = temp[2]*cmat; temp[3] = temp[3]*cmat; + Planef portal_plane(temp[0], temp[1], temp[2]); + if (!is_facing_view(portal_plane)) + return; + pgraph_cat.spam() << "after transformation to camera space" << endl; pgraph_cat.spam() << temp[0] << endl; pgraph_cat.spam() << temp[1] << endl; @@ -275,9 +279,6 @@ prepare_portal(const NodePath &node_path) pgraph_cat.spam() << "min_x " << min_x << ";max_x " << max_x << ";min_z " << min_z << ";max_z " << max_z << endl; - - Planef portal_plane(temp[0], temp[1], temp[2]); - float y; y = get_plane_depth(min_x, min_z, &portal_plane); @@ -303,7 +304,7 @@ prepare_portal(const NodePath &node_path) pgraph_cat.spam() << _coords[3] << endl; // check if portal is in view - if (is_in_view(node_path)) { + if (is_whole_portal_in_view(node_path)) { pgraph_cat.debug() << "portal passed 1st level test \n"; // ok, now lets add the original portal @@ -376,7 +377,7 @@ clip_portal(const NodePath &node_path) from_direction = _coords[(j+1)%_num_vert] - _coords[j]; is_intersect = plane.intersects_line(t, from_origin, from_direction); if (is_intersect && (t > 0.0 && t < 1.0)) { - pgraph_cat.debug() << "bottom plane intersected segement " << j << "->" + pgraph_cat.debug() << "bottom plane intersected segment " << j << "->" << (j+1)%_num_vert << " at t=" << t << endl; cut_point = from_origin + t*from_direction; pgraph_cat.debug() << "cut_point: " << cut_point << endl; @@ -400,7 +401,7 @@ clip_portal(const NodePath &node_path) from_direction = _coords[(j+1)%_num_vert] - _coords[j]; is_intersect = plane.intersects_line(t, from_origin, from_direction); if (is_intersect && (t > 0.0 && t < 1.0)) { - pgraph_cat.debug() << "top plane intersected segement " << j << "->" + pgraph_cat.debug() << "top plane intersected segment " << j << "->" << (j+1)%_num_vert << " at t=" << t << endl; cut_point = from_origin + t*from_direction; pgraph_cat.debug() << "cut_point: " << cut_point << endl; @@ -424,7 +425,7 @@ clip_portal(const NodePath &node_path) from_direction = _coords[(j+1)%_num_vert] - _coords[j]; is_intersect = plane.intersects_line(t, from_origin, from_direction); if (is_intersect && (t > 0.0 && t < 1.0)) { - pgraph_cat.debug() << "right plane intersected segement " << j << "->" + pgraph_cat.debug() << "right plane intersected segment " << j << "->" << (j+1)%_num_vert << " at t=" << t << endl; cut_point = from_origin + t*from_direction; pgraph_cat.debug() << "cut_point: " << cut_point << endl; @@ -448,7 +449,7 @@ clip_portal(const NodePath &node_path) from_direction = _coords[(j+1)%_num_vert] - _coords[j]; is_intersect = plane.intersects_line(t, from_origin, from_direction); if (is_intersect && (t > 0.0 && t < 1.0)) { - pgraph_cat.debug() << "left plane intersected segement " << j << "->" + pgraph_cat.debug() << "left plane intersected segment " << j << "->" << (j+1)%_num_vert << " at t=" << t << endl; cut_point = from_origin + t*from_direction; pgraph_cat.debug() << "cut_point: " << cut_point << endl; @@ -473,7 +474,7 @@ clip_portal(const NodePath &node_path) draw_to(_coords[0]); // 2nd level test, more accurate to determine if the portal is worth visiting - if (!is_facing_camera(node_path)) { + if (!is_partial_portal_in_view(node_path)) { pgraph_cat.debug() << "portal failed 2nd level test \n"; _num_vert = 0; } @@ -562,13 +563,11 @@ get_reduced_frustum(const NodePath &node_path) _view_frustum->get_point(4), _view_frustum->get_point(5), _view_frustum->get_point(6), _view_frustum->get_point(7)); - pgraph_cat.spam() << *reduced_frustum << endl; + pgraph_cat.debug() << *reduced_frustum << endl; // draw this hexahedron _color = Colorf(0,0,1,1); draw_hexahedron(DCAST(BoundingHexahedron, reduced_frustum)); - _reduced_frustum = DCAST(BoundingHexahedron, reduced_frustum); - return reduced_frustum; } diff --git a/panda/src/pgraph/portalClipper.h b/panda/src/pgraph/portalClipper.h index 49409ae6d3..e38bd6fd35 100755 --- a/panda/src/pgraph/portalClipper.h +++ b/panda/src/pgraph/portalClipper.h @@ -63,12 +63,12 @@ public: PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup); ~PortalClipper(); - INLINE bool is_in_view(const NodePath &node_path); - INLINE bool is_facing_camera(const NodePath &node_path); + INLINE bool is_whole_portal_in_view(const NodePath &node_path); + INLINE bool is_partial_portal_in_view(const NodePath &node_path); + INLINE bool is_facing_view(Planef portal_plane); + void prepare_portal(const NodePath &node_path); - void clip_portal(const NodePath &node_path); - PT(BoundingVolume) get_reduced_frustum(const NodePath &node_path); void draw_lines(); @@ -83,7 +83,7 @@ public: INLINE float get_plane_depth(float x, float z, Planef *portal_plane); - INLINE void set_reduced_frustum(BoundingHexahedron *frustum); + INLINE void set_view_frustum(BoundingHexahedron *frustum); public: static TypeHandle get_class_type() { @@ -129,7 +129,6 @@ private: PT(GeomLinestrip) _geom_linestrip; BoundingHexahedron *_view_frustum; - BoundingHexahedron *_reduced_frustum; PortalNode *_portal_node; // current working portal for dereference ease diff --git a/panda/src/pgraph/portalNode.cxx b/panda/src/pgraph/portalNode.cxx index e48fdaee5a..e0e49ef0e5 100755 --- a/panda/src/pgraph/portalNode.cxx +++ b/panda/src/pgraph/portalNode.cxx @@ -48,7 +48,7 @@ PortalNode(const string &name) : { _zone_in = NULL; _zone_out = NULL; - _visible = false; + _visible = true; } //////////////////////////////////////////////////////////////////// @@ -65,7 +65,7 @@ PortalNode(const PortalNode ©) : { _zone_in = NULL; _zone_out = NULL; - _visible = false; + _visible = true; } //////////////////////////////////////////////////////////////////// @@ -180,28 +180,30 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { PortalClipper *portal_viewer = trav->get_portal_clipper(); if (!_zone_out.is_empty() && portal_viewer) { //CullTraverserData next_data(data, _zone_out); - if (is_visible()) { - pgraph_cat.debug() << "portal node visible " << *this << endl; - PT(GeometricBoundingVolume) vf = trav->get_view_frustum(); - PT(BoundingVolume) reduced_frustum; + pgraph_cat.debug() << "checking portal node " << *this << endl; + PT(GeometricBoundingVolume) vf = trav->get_view_frustum(); + PT(BoundingVolume) reduced_frustum; + + // following three functions do nothing, if the portal is not visible + portal_viewer->prepare_portal(data._node_path.get_node_path()); + portal_viewer->clip_portal(data._node_path.get_node_path()); + if ((reduced_frustum = portal_viewer->get_reduced_frustum(data._node_path.get_node_path()))) { + // This reduced frustum is in camera space + pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl; + vf = DCAST(GeometricBoundingVolume, reduced_frustum); + + portal_viewer->set_view_frustum(DCAST(BoundingHexahedron,vf->make_copy())); + + // trasform it to cull_center space + CPT(TransformState) cull_center_transform = + portal_viewer->_scene_setup->get_cull_center().get_transform(_zone_out); + vf->xform(cull_center_transform->get_mat()); - portal_viewer->prepare_portal(data._node_path.get_node_path()); - portal_viewer->clip_portal(data._node_path.get_node_path()); - if ((reduced_frustum = portal_viewer->get_reduced_frustum(data._node_path.get_node_path()))) { - // This reduced frustum is in camera space - pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl; - vf = DCAST(GeometricBoundingVolume, reduced_frustum); - - // trasform it to cull_center space - CPT(TransformState) cull_center_transform = - portal_viewer->_scene_setup->get_cull_center().get_transform(_zone_out); - vf->xform(cull_center_transform->get_mat()); - } pgraph_cat.spam() << "vf is " << *vf << "\n"; - + // Get the net trasform of the _zone_out CPT(TransformState) zone_transform = _zone_out.get_net_transform(); - + CullTraverserData next_data(_zone_out, trav->get_render_transform()->compose(zone_transform), zone_transform, trav->get_initial_state(), vf,