patch by Josh Enes (bug 1074173)

This commit is contained in:
rdb 2013-10-22 12:32:15 +00:00
parent 829e79cf29
commit 8383427022

View File

@ -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;