mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
fixed a bug with multiple sibling portals in view at the same time
This commit is contained in:
parent
af31909359
commit
5a19e97534
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -63,9 +63,9 @@ PortalNode(const PortalNode ©) :
|
||||
_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.
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user