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
// 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::
set_view_frustum(BoundingHexahedron *frustum) {
_view_frustum = frustum;
set_reduced_frustum(BoundingHexahedron *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
// Access: Public
@ -118,9 +128,8 @@ set_view_frustum(BoundingHexahedron *frustum) {
// 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));
is_facing_view(Planef portal_plane) {
Planef view_plane(_reduced_frustum->get_point(4), _reduced_frustum->get_point(5), _reduced_frustum->get_point(6));
// use the view_frustum's near plane to calculate direction
pgraph_cat.spam() << portal_plane.get_normal() << "; " << -view_plane.get_normal() << endl;
@ -134,24 +143,21 @@ is_facing_view(Planef portal_plane)
// 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
// is a 2nd level test to weed out most of the portals
////////////////////////////////////////////////////////////////////
INLINE bool PortalClipper::
is_whole_portal_in_view(const NodePath &node_path) {
const BoundingVolume *bv = &_portal_node->get_bound();
is_whole_portal_in_view(LMatrix4f cmat) {
// I am about to xform this gbv, so lets make a copy
const BoundingVolume *bv = &_portal_node->get_bound();
BoundingVolume *cbv = bv->make_copy();
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, cbv);
// trasform it to camera space
CPT(TransformState) ctransform = node_path.get_transform(_scene_setup->get_cull_center());
gbv->xform(ctransform->get_mat());
gbv->xform(cmat);
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);
}
@ -163,14 +169,14 @@ is_whole_portal_in_view(const NodePath &node_path) {
// test to make sure this portal is worth visiting
////////////////////////////////////////////////////////////////////
INLINE bool PortalClipper::
is_partial_portal_in_view(const NodePath &node_path) {
is_partial_portal_in_view() {
int result = 0;
// check if any of the _coords in tested frustum
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);
}

View File

@ -47,7 +47,7 @@ PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup) {
_geom_point = new GeomPoint;
_geom_linestrip = new GeomLinestrip;
_view_frustum = DCAST(BoundingHexahedron, frustum);
_view_frustum = _reduced_frustum = DCAST(BoundingHexahedron, frustum);
_scene_setup = scene_setup;
}
@ -306,7 +306,7 @@ prepare_portal(const NodePath &node_path)
pgraph_cat.spam() << _coords[3] << endl;
// 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
_color = Colorf(0,1,1,1);
move_to(temp[0]);
@ -339,23 +339,9 @@ prepare_portal(const NodePath &node_path)
void PortalClipper::
clip_portal(const NodePath &node_path)
{
int num_planes = _view_frustum->get_num_planes();
if (!_num_vert)
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
// Plane0 -> far plane -> None
// plane5 -> near plane -> None
@ -374,7 +360,7 @@ clip_portal(const NodePath &node_path)
LVector3f from_direction;
// 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) {
from_origin = _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";
}
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
plane = _view_frustum->get_plane(3);
plane = _reduced_frustum->get_plane(3);
for (j=0; j<_num_vert; ++j) {
from_origin = _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";
}
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
plane = _view_frustum->get_plane(2);
plane = _reduced_frustum->get_plane(2);
for (j=0; j<_num_vert; ++j) {
from_origin = _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";
}
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
plane = _view_frustum->get_plane(4);
plane = _reduced_frustum->get_plane(4);
for (j=0; j<_num_vert; ++j) {
from_origin = _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";
}
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
_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
return;
}
if (!is_partial_portal_in_view(node_path)) {
if (!is_partial_portal_in_view()) {
pgraph_cat.debug() << "portal failed 3rd level test \n";
_num_vert = 0;
}
@ -522,10 +508,11 @@ get_reduced_frustum(const NodePath &node_path)
float t;
bool visible = true;
// 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;
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
pgraph_cat.spam() << "far plane intersected 7->3 at t=" << t << endl;
intersect_points[0] = from_origin + t*from_direction;
@ -535,9 +522,9 @@ get_reduced_frustum(const NodePath &node_path)
visible = false;
// 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;
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
pgraph_cat.spam() << "far plane intersected 4->0 at t=" << t << endl;
intersect_points[1] = from_origin + t*from_direction;
@ -547,9 +534,9 @@ get_reduced_frustum(const NodePath &node_path)
visible = false;
// 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;
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
pgraph_cat.spam() << "far plane intersected 5->1 at t=" << t << endl;
intersect_points[2] = from_origin + t*from_direction;
@ -559,9 +546,9 @@ get_reduced_frustum(const NodePath &node_path)
visible = false;
// 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;
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
pgraph_cat.spam() << "far plane intersected 6->2 at t=" << t << endl;
intersect_points[3] = from_origin + t*from_direction;
@ -579,8 +566,8 @@ get_reduced_frustum(const NodePath &node_path)
PT(BoundingVolume) reduced_frustum = new
BoundingHexahedron(intersect_points[1], intersect_points[2],
intersect_points[3], intersect_points[0],
_view_frustum->get_point(4), _view_frustum->get_point(5),
_view_frustum->get_point(6), _view_frustum->get_point(7));
_reduced_frustum->get_point(4), _reduced_frustum->get_point(5),
_reduced_frustum->get_point(6), _reduced_frustum->get_point(7));
pgraph_cat.debug() << *reduced_frustum << endl;

View File

@ -63,9 +63,9 @@ public:
PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup);
~PortalClipper();
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_partial_portal_in_view();
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 clip_portal(const NodePath &node_path);
@ -83,7 +83,8 @@ public:
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:
static TypeHandle get_class_type() {
@ -129,6 +130,7 @@ private:
PT(GeomLinestrip) _geom_linestrip;
BoundingHexahedron *_view_frustum;
BoundingHexahedron *_reduced_frustum;
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),
_flags(copy._flags)
{
_zone_in = NULL;
_zone_out = NULL;
_visible = true;
_zone_in = copy._zone_in;
_zone_out = copy._zone_in;
_visible = copy._visible;
}
////////////////////////////////////////////////////////////////////
@ -192,7 +192,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
pgraph_cat.debug() << "got reduced frustum " << reduced_frustum << endl;
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
CPT(TransformState) cull_center_transform =
@ -208,12 +209,22 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
zone_transform,
trav->get_initial_state(), vf,
trav->get_guard_band());
pgraph_cat.spam() << "cull_callback: traversing " << _zone_out.get_name() << endl;
// Make this zone show with the reduced frustum
_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);
// make sure traverser is not drawing this node again
_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.

View File

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