fixed a bug with multiple sibling portals in view at the same time

This commit is contained in:
Asad M. Zaman 2004-06-09 00:48:05 +00:00
parent af31909359
commit 5a19e97534
5 changed files with 69 additions and 62 deletions

View File

@ -101,16 +101,26 @@ draw_camera_frustum() {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PortalClipper::set_view_frustum // Function: PortalClipper::set_reduced_frustum
// Access: Public // Access: Public
// Description: set the current view frustum before traversing // Description: Set the current view frustum that is being calculated
// by the portal clipper
// //
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void PortalClipper:: INLINE void PortalClipper::
set_view_frustum(BoundingHexahedron *frustum) { set_reduced_frustum(BoundingHexahedron *frustum) {
_view_frustum = frustum; _reduced_frustum = frustum;
} }
////////////////////////////////////////////////////////////////////
// Function: PortalClipper::get_reduced_frustum
// Access: Published
// Description: Return the reduced frustum
////////////////////////////////////////////////////////////////////
INLINE BoundingHexahedron *PortalClipper::
get_reduced_frustum() const {
return _reduced_frustum;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PortalClipper::is_facing_view // Function: PortalClipper::is_facing_view
// Access: Public // Access: Public
@ -118,9 +128,8 @@ set_view_frustum(BoundingHexahedron *frustum) {
// is facing the camera's near plane // is facing the camera's near plane
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool PortalClipper:: INLINE bool PortalClipper::
is_facing_view(Planef portal_plane) is_facing_view(Planef portal_plane) {
{ Planef view_plane(_reduced_frustum->get_point(4), _reduced_frustum->get_point(5), _reduced_frustum->get_point(6));
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 // use the view_frustum's near plane to calculate direction
pgraph_cat.spam() << portal_plane.get_normal() << "; " << -view_plane.get_normal() << endl; pgraph_cat.spam() << portal_plane.get_normal() << "; " << -view_plane.get_normal() << endl;
@ -134,24 +143,21 @@ is_facing_view(Planef portal_plane)
// Access: Public // Access: Public
// Description: checks if portal_node is within the view frustum. // Description: checks if portal_node is within the view frustum.
// If so, then the portal is worth considering. This // If so, then the portal is worth considering. This
// is a 1st level test to weed out most of the portals // is a 2nd level test to weed out most of the portals
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool PortalClipper:: INLINE bool PortalClipper::
is_whole_portal_in_view(const NodePath &node_path) { is_whole_portal_in_view(LMatrix4f cmat) {
const BoundingVolume *bv = &_portal_node->get_bound();
// I am about to xform this gbv, so lets make a copy // I am about to xform this gbv, so lets make a copy
const BoundingVolume *bv = &_portal_node->get_bound();
BoundingVolume *cbv = bv->make_copy(); BoundingVolume *cbv = bv->make_copy();
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, cbv); GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, cbv);
// trasform it to camera space // trasform it to camera space
CPT(TransformState) ctransform = node_path.get_transform(_scene_setup->get_cull_center()); gbv->xform(cmat);
gbv->xform(ctransform->get_mat());
int result = _view_frustum->contains(gbv); int result = _reduced_frustum->contains(gbv);
pgraph_cat.spam() << "1st level test if portal: " << *_view_frustum << " is in view " << result << endl; pgraph_cat.spam() << "1st level test if portal: " << *_reduced_frustum << " is in view " << result << endl;
return (result != 0); return (result != 0);
} }
@ -163,14 +169,14 @@ is_whole_portal_in_view(const NodePath &node_path) {
// test to make sure this portal is worth visiting // test to make sure this portal is worth visiting
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool PortalClipper:: INLINE bool PortalClipper::
is_partial_portal_in_view(const NodePath &node_path) { is_partial_portal_in_view() {
int result = 0; int result = 0;
// check if any of the _coords in tested frustum // check if any of the _coords in tested frustum
for (int j=0; j<_num_vert; ++j) { for (int j=0; j<_num_vert; ++j) {
result |= _view_frustum->contains(_coords[j]); result |= _reduced_frustum->contains(_coords[j]);
} }
pgraph_cat.spam() << "frustum: " << *_view_frustum << " contains(coord) result = " << result << endl; pgraph_cat.spam() << "frustum: " << *_reduced_frustum << " contains(coord) result = " << result << endl;
return (result != 0); return (result != 0);
} }

View File

@ -47,7 +47,7 @@ PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup) {
_geom_point = new GeomPoint; _geom_point = new GeomPoint;
_geom_linestrip = new GeomLinestrip; _geom_linestrip = new GeomLinestrip;
_view_frustum = DCAST(BoundingHexahedron, frustum); _view_frustum = _reduced_frustum = DCAST(BoundingHexahedron, frustum);
_scene_setup = scene_setup; _scene_setup = scene_setup;
} }
@ -306,7 +306,7 @@ prepare_portal(const NodePath &node_path)
pgraph_cat.spam() << _coords[3] << endl; pgraph_cat.spam() << _coords[3] << endl;
// check if portal is in view // check if portal is in view
if (is_whole_portal_in_view(node_path)) { if (is_whole_portal_in_view(cmat)) {
// ok, now lets add the original portal // ok, now lets add the original portal
_color = Colorf(0,1,1,1); _color = Colorf(0,1,1,1);
move_to(temp[0]); move_to(temp[0]);
@ -339,23 +339,9 @@ prepare_portal(const NodePath &node_path)
void PortalClipper:: void PortalClipper::
clip_portal(const NodePath &node_path) clip_portal(const NodePath &node_path)
{ {
int num_planes = _view_frustum->get_num_planes();
if (!_num_vert) if (!_num_vert)
return; return;
/*
pgraph_cat.debug() << "Number of planes " << num_planes << endl;
// print out the planes. plane 0 should be far and plane 5 should be near
// so we are only concerned with the 4 side planes.
for (int i=0; i<num_planes; ++i) {
Planef plane = _view_frustum->get_plane(i);
plane.output(pgraph_cat.debug());
pgraph_cat.debug() << endl;
}
*/
// ViewFrustum -> Logical Planes -> Portal Edge // ViewFrustum -> Logical Planes -> Portal Edge
// Plane0 -> far plane -> None // Plane0 -> far plane -> None
// plane5 -> near plane -> None // plane5 -> near plane -> None
@ -374,7 +360,7 @@ clip_portal(const NodePath &node_path)
LVector3f from_direction; LVector3f from_direction;
// Look for intersection with the view frustum's bottom_plane and portal edges // Look for intersection with the view frustum's bottom_plane and portal edges
plane = _view_frustum->get_plane(1); plane = _reduced_frustum->get_plane(1);
for (j=0; j<_num_vert; ++j) { for (j=0; j<_num_vert; ++j) {
from_origin = _coords[j]; from_origin = _coords[j];
from_direction = _coords[(j+1)%_num_vert] - _coords[j]; from_direction = _coords[(j+1)%_num_vert] - _coords[j];
@ -397,11 +383,11 @@ clip_portal(const NodePath &node_path)
pgraph_cat.debug() << "ignored for now for simplicity \n"; pgraph_cat.debug() << "ignored for now for simplicity \n";
} }
else else
pgraph_cat.debug() << "is_intersect: " << is_intersect << " at t = " << t << endl; pgraph_cat.spam() << "is_intersect: " << is_intersect << " at t = " << t << endl;
} }
// Look for intersection with the view frustum's top_plane and portal edges // Look for intersection with the view frustum's top_plane and portal edges
plane = _view_frustum->get_plane(3); plane = _reduced_frustum->get_plane(3);
for (j=0; j<_num_vert; ++j) { for (j=0; j<_num_vert; ++j) {
from_origin = _coords[j]; from_origin = _coords[j];
from_direction = _coords[(j+1)%_num_vert] - _coords[j]; from_direction = _coords[(j+1)%_num_vert] - _coords[j];
@ -424,11 +410,11 @@ clip_portal(const NodePath &node_path)
pgraph_cat.debug() << "ignored for now for simplicity \n"; pgraph_cat.debug() << "ignored for now for simplicity \n";
} }
else else
pgraph_cat.debug() << "is_intersect: " << is_intersect << " at t = " << t << endl; pgraph_cat.spam() << "is_intersect: " << is_intersect << " at t = " << t << endl;
} }
// Look for intersection with the view frustum's right_plane and portal edges // Look for intersection with the view frustum's right_plane and portal edges
plane = _view_frustum->get_plane(2); plane = _reduced_frustum->get_plane(2);
for (j=0; j<_num_vert; ++j) { for (j=0; j<_num_vert; ++j) {
from_origin = _coords[j]; from_origin = _coords[j];
from_direction = _coords[(j+1)%_num_vert] - _coords[j]; from_direction = _coords[(j+1)%_num_vert] - _coords[j];
@ -451,11 +437,11 @@ clip_portal(const NodePath &node_path)
pgraph_cat.debug() << "ignored for now for simplicity \n"; pgraph_cat.debug() << "ignored for now for simplicity \n";
} }
else else
pgraph_cat.debug() << "is_intersect: " << is_intersect << " at t = " << t << endl; pgraph_cat.spam() << "is_intersect: " << is_intersect << " at t = " << t << endl;
} }
// Look for intersection with the view frustum's left_plane and portal edges // Look for intersection with the view frustum's left_plane and portal edges
plane = _view_frustum->get_plane(4); plane = _reduced_frustum->get_plane(4);
for (j=0; j<_num_vert; ++j) { for (j=0; j<_num_vert; ++j) {
from_origin = _coords[j]; from_origin = _coords[j];
from_direction = _coords[(j+1)%_num_vert] - _coords[j]; from_direction = _coords[(j+1)%_num_vert] - _coords[j];
@ -478,7 +464,7 @@ clip_portal(const NodePath &node_path)
pgraph_cat.debug() << "ignored for now for simplicity \n"; pgraph_cat.debug() << "ignored for now for simplicity \n";
} }
else else
pgraph_cat.debug() << "is_intersect: " << is_intersect << " at t = " << t << endl; pgraph_cat.spam() << "is_intersect: " << is_intersect << " at t = " << t << endl;
} }
// ok, now lets add the clipped portal // ok, now lets add the clipped portal
_color = Colorf(1,0,0,1); _color = Colorf(1,0,0,1);
@ -493,7 +479,7 @@ clip_portal(const NodePath &node_path)
if (xect == 0xf) { //if all four planes intersected the portal, it is visible if (xect == 0xf) { //if all four planes intersected the portal, it is visible
return; return;
} }
if (!is_partial_portal_in_view(node_path)) { if (!is_partial_portal_in_view()) {
pgraph_cat.debug() << "portal failed 3rd level test \n"; pgraph_cat.debug() << "portal failed 3rd level test \n";
_num_vert = 0; _num_vert = 0;
} }
@ -522,10 +508,11 @@ get_reduced_frustum(const NodePath &node_path)
float t; float t;
bool visible = true; bool visible = true;
// find intersection of 7->3 with far // find intersection of 7->3 with far
LPoint3f from_origin = _view_frustum->get_point(7); LPoint3f from_origin = _reduced_frustum->get_point(7);
LVector3f from_direction = _coords[3] - from_origin; LVector3f from_direction = _coords[3] - from_origin;
bool is_intersect = _view_frustum->get_plane(0).intersects_line(t, from_origin, from_direction); bool is_intersect = _reduced_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
pgraph_cat.spam() << "far plane intersected 7->3 at t=" << t << endl; pgraph_cat.spam() << "far plane intersected 7->3 at t=" << t << endl;
intersect_points[0] = from_origin + t*from_direction; intersect_points[0] = from_origin + t*from_direction;
@ -535,9 +522,9 @@ get_reduced_frustum(const NodePath &node_path)
visible = false; visible = false;
// find intersection of 4->0 with far // find intersection of 4->0 with far
from_origin = _view_frustum->get_point(4); from_origin = _reduced_frustum->get_point(4);
from_direction = _coords[0] - from_origin; from_direction = _coords[0] - from_origin;
is_intersect = _view_frustum->get_plane(0).intersects_line(t, from_origin, from_direction); is_intersect = _reduced_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
pgraph_cat.spam() << "far plane intersected 4->0 at t=" << t << endl; pgraph_cat.spam() << "far plane intersected 4->0 at t=" << t << endl;
intersect_points[1] = from_origin + t*from_direction; intersect_points[1] = from_origin + t*from_direction;
@ -547,9 +534,9 @@ get_reduced_frustum(const NodePath &node_path)
visible = false; visible = false;
// find intersection of 5->1 with far // find intersection of 5->1 with far
from_origin = _view_frustum->get_point(5); from_origin = _reduced_frustum->get_point(5);
from_direction = _coords[1] - from_origin; from_direction = _coords[1] - from_origin;
is_intersect = _view_frustum->get_plane(0).intersects_line(t, from_origin, from_direction); is_intersect = _reduced_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
pgraph_cat.spam() << "far plane intersected 5->1 at t=" << t << endl; pgraph_cat.spam() << "far plane intersected 5->1 at t=" << t << endl;
intersect_points[2] = from_origin + t*from_direction; intersect_points[2] = from_origin + t*from_direction;
@ -559,9 +546,9 @@ get_reduced_frustum(const NodePath &node_path)
visible = false; visible = false;
// find intersection of 6->2 with far // find intersection of 6->2 with far
from_origin = _view_frustum->get_point(6); from_origin = _reduced_frustum->get_point(6);
from_direction = _coords[2] - from_origin; from_direction = _coords[2] - from_origin;
is_intersect = _view_frustum->get_plane(0).intersects_line(t, from_origin, from_direction); is_intersect = _reduced_frustum->get_plane(0).intersects_line(t, from_origin, from_direction);
if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal if (is_intersect && t >= 0.0) { // has to be positive, else camera is not looking at the portal
pgraph_cat.spam() << "far plane intersected 6->2 at t=" << t << endl; pgraph_cat.spam() << "far plane intersected 6->2 at t=" << t << endl;
intersect_points[3] = from_origin + t*from_direction; intersect_points[3] = from_origin + t*from_direction;
@ -579,8 +566,8 @@ get_reduced_frustum(const NodePath &node_path)
PT(BoundingVolume) reduced_frustum = new PT(BoundingVolume) reduced_frustum = new
BoundingHexahedron(intersect_points[1], intersect_points[2], BoundingHexahedron(intersect_points[1], intersect_points[2],
intersect_points[3], intersect_points[0], intersect_points[3], intersect_points[0],
_view_frustum->get_point(4), _view_frustum->get_point(5), _reduced_frustum->get_point(4), _reduced_frustum->get_point(5),
_view_frustum->get_point(6), _view_frustum->get_point(7)); _reduced_frustum->get_point(6), _reduced_frustum->get_point(7));
pgraph_cat.debug() << *reduced_frustum << endl; pgraph_cat.debug() << *reduced_frustum << endl;

View File

@ -63,9 +63,9 @@ public:
PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup); PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup);
~PortalClipper(); ~PortalClipper();
INLINE bool is_whole_portal_in_view(const NodePath &node_path); INLINE bool is_partial_portal_in_view();
INLINE bool is_partial_portal_in_view(const NodePath &node_path);
INLINE bool is_facing_view(Planef portal_plane); INLINE bool is_facing_view(Planef portal_plane);
INLINE bool is_whole_portal_in_view(LMatrix4f cmat);
void prepare_portal(const NodePath &node_path); void prepare_portal(const NodePath &node_path);
void clip_portal(const NodePath &node_path); void clip_portal(const NodePath &node_path);
@ -83,7 +83,8 @@ public:
INLINE float get_plane_depth(float x, float z, Planef *portal_plane); INLINE float get_plane_depth(float x, float z, Planef *portal_plane);
INLINE void set_view_frustum(BoundingHexahedron *frustum); INLINE BoundingHexahedron *get_reduced_frustum() const;
INLINE void set_reduced_frustum(BoundingHexahedron *bh);
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {
@ -129,6 +130,7 @@ private:
PT(GeomLinestrip) _geom_linestrip; PT(GeomLinestrip) _geom_linestrip;
BoundingHexahedron *_view_frustum; BoundingHexahedron *_view_frustum;
BoundingHexahedron *_reduced_frustum;
PortalNode *_portal_node; // current working portal for dereference ease PortalNode *_portal_node; // current working portal for dereference ease

View File

@ -63,9 +63,9 @@ PortalNode(const PortalNode &copy) :
_into_portal_mask(copy._into_portal_mask), _into_portal_mask(copy._into_portal_mask),
_flags(copy._flags) _flags(copy._flags)
{ {
_zone_in = NULL; _zone_in = copy._zone_in;
_zone_out = NULL; _zone_out = copy._zone_in;
_visible = true; _visible = copy._visible;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -192,7 +192,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl; pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl;
vf = DCAST(GeometricBoundingVolume, reduced_frustum); vf = DCAST(GeometricBoundingVolume, reduced_frustum);
portal_viewer->set_view_frustum(DCAST(BoundingHexahedron,vf->make_copy())); // keep a copy of this reduced frustum
BoundingHexahedron *new_bh = DCAST(BoundingHexahedron, vf->make_copy());
// trasform it to cull_center space // trasform it to cull_center space
CPT(TransformState) cull_center_transform = CPT(TransformState) cull_center_transform =
@ -208,12 +209,22 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
zone_transform, zone_transform,
trav->get_initial_state(), vf, trav->get_initial_state(), vf,
trav->get_guard_band()); trav->get_guard_band());
pgraph_cat.spam() << "cull_callback: traversing " << _zone_out.get_name() << endl; pgraph_cat.spam() << "cull_callback: traversing " << _zone_out.get_name() << endl;
// Make this zone show with the reduced frustum // Make this zone show with the reduced frustum
_zone_out.show(); _zone_out.show();
// all nodes visible through this portal, should have this node's frustum
BoundingHexahedron *old_bh = portal_viewer->get_reduced_frustum();
portal_viewer->set_reduced_frustum(new_bh);
trav->traverse(next_data); trav->traverse(next_data);
// make sure traverser is not drawing this node again // make sure traverser is not drawing this node again
_zone_out.hide(); _zone_out.hide();
// reset portal viewer frustum for the siblings;
portal_viewer->set_reduced_frustum(old_bh);
} }
} }
// Now carry on to render our child nodes. // Now carry on to render our child nodes.

View File

@ -77,6 +77,7 @@ PUBLISHED:
INLINE void set_visible(bool value); INLINE void set_visible(bool value);
INLINE bool is_visible(); INLINE bool is_visible();
protected: protected:
virtual BoundingVolume *recompute_bound(); virtual BoundingVolume *recompute_bound();
virtual BoundingVolume *recompute_internal_bound(); virtual BoundingVolume *recompute_internal_bound();