From 8383427022d8bb9d8718abb0e1711ff7d9baca99 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 22 Oct 2013 12:32:15 +0000 Subject: [PATCH] patch by Josh Enes (bug 1074173) --- panda/src/pgraph/cullPlanes.cxx | 75 +++++++++------------------------ 1 file changed, 19 insertions(+), 56 deletions(-) diff --git a/panda/src/pgraph/cullPlanes.cxx b/panda/src/pgraph/cullPlanes.cxx index ae8ca10408..cc02bab922 100644 --- a/panda/src/pgraph/cullPlanes.cxx +++ b/panda/src/pgraph/cullPlanes.cxx @@ -202,12 +202,12 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data, } // Get the occluder geometry in cull-center space. - const LMatrix4 &occluder_mat = occluder_transform->get_mat(); + const LMatrix4 &occluder_mat_cull = occluder_transform->get_mat(); LPoint3 points_near[4]; - points_near[0] = occluder_node->get_vertex(0) * occluder_mat; - points_near[1] = occluder_node->get_vertex(1) * occluder_mat; - points_near[2] = occluder_node->get_vertex(2) * occluder_mat; - points_near[3] = occluder_node->get_vertex(3) * occluder_mat; + points_near[0] = occluder_node->get_vertex(0) * occluder_mat_cull; + points_near[1] = occluder_node->get_vertex(1) * occluder_mat_cull; + points_near[2] = occluder_node->get_vertex(2) * occluder_mat_cull; + points_near[3] = occluder_node->get_vertex(3) * occluder_mat_cull; LPlane plane(points_near[0], points_near[1], points_near[2]); if (plane.get_normal().dot(LVector3::forward()) >= 0.0) { @@ -225,49 +225,6 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data, } } - PN_stdfloat near_clip = lens->get_near(); - if (plane.dist_to_plane(LPoint3::zero()) <= near_clip) { - // This occluder is behind the camera's near plane. Ignore it. - if (pgraph_cat.is_spam()) { - pgraph_cat.spam() - << "Ignoring occluder " << occluder << ": behind near plane.\n"; - } - continue; - } - - PN_stdfloat d0 = points_near[0].dot(LVector3::forward()); - PN_stdfloat d1 = points_near[1].dot(LVector3::forward()); - PN_stdfloat d2 = points_near[2].dot(LVector3::forward()); - PN_stdfloat d3 = points_near[3].dot(LVector3::forward()); - - if (d0 <= near_clip && d1 <= near_clip && d2 <= near_clip && d3 <= near_clip) { - // All four corners of the occluder are behind the camera's - // near plane. Ignore it. - if (pgraph_cat.is_spam()) { - pgraph_cat.spam() - << "Ignoring occluder " << occluder << ": behind near plane (test 2).\n"; - } - continue; - } - - // TODO: it's possible for part of the occlusion polygon to - // intersect the camera's y = 0 plane. If this happens, the - // frustum will go insane and the occluder won't work. The - // proper fix for this is to clip the polygon against the near - // plane, producing a smaller polygon, and use that to - // generate the frustum. But maybe it doesn't matter. In - // lieu of this, we just toss out any occluder with *any* - // corner behind the y = 0 plane. - if (d0 <= 0.0 || d1 <= 0.0 || d2 <= 0.0 || d3 <= 0.0) { - // One of the corners is behind the y = 0 plane. We can't - // handle this case. Ignore it. - if (pgraph_cat.is_spam()) { - pgraph_cat.spam() - << "Ignoring occluder " << occluder << ": partly behind zero plane.\n"; - } - continue; - } - if (occluder_node->get_min_coverage()) { LPoint3 coords[4]; lens->project(points_near[0], coords[0]); @@ -318,22 +275,28 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data, // TODO: perhaps we should also check whether any existing // occluders are fully contained within this new one. - // Project those four lines to the camera's far plane. - PN_stdfloat far_clip = scene->get_lens()->get_far(); - LPlane far_plane(-LVector3::forward(), LVector3::forward() * far_clip); + // Get the occluder coordinates in global space. + const LMatrix4 &occluder_mat = occluder.get_net_transform()->get_mat(); + points_near[0] = occluder_node->get_vertex(0) * occluder_mat; + points_near[1] = occluder_node->get_vertex(1) * occluder_mat; + points_near[2] = occluder_node->get_vertex(2) * occluder_mat; + points_near[3] = occluder_node->get_vertex(3) * occluder_mat; + // For the far points, project PAST the far clip of the lens + // to ensures we get stuff that might be intersecting the far clip. + LPoint3 center = scene->get_cull_center().get_net_transform()->get_pos(); + PN_stdfloat far_clip = scene->get_lens()->get_far() * 2.0; LPoint3 points_far[4]; - far_plane.intersects_line(points_far[0], LPoint3::zero(), points_near[0]); - far_plane.intersects_line(points_far[1], LPoint3::zero(), points_near[1]); - far_plane.intersects_line(points_far[2], LPoint3::zero(), points_near[2]); - far_plane.intersects_line(points_far[3], LPoint3::zero(), points_near[3]); + points_far[0] = normalize(points_near[0] - center) * far_clip + points_near[0]; + points_far[1] = normalize(points_near[1] - center) * far_clip + points_near[1]; + points_far[2] = normalize(points_near[2] - center) * far_clip + points_near[2]; + points_far[3] = normalize(points_near[3] - center) * far_clip + points_near[3]; // With these points, construct the bounding frustum of the // occluded region. PT(BoundingHexahedron) frustum = new BoundingHexahedron(points_far[1], points_far[2], points_far[3], points_far[0], points_near[1], points_near[2], points_near[3], points_near[0]); - frustum->xform(center_transform->get_mat()); new_planes->_occluders[occluder] = frustum;