// // Test primitives against a viewing frustrum. // // Copyright (c) J. Belson 2003.05.29 // // $Author: jon $ : $Date: 2003/05/30 17:50:44 $ // #include #include "frustrum.h" #include "point3d.h" /** * Constructor. * Define a viewing frustrum using the field of view angle * and the near and far clipping panes. */ frustrum::frustrum(float view_angle, float near_plane, float far_plane) { fov = view_angle; near = -near_plane; far = -far_plane; k = 1.0/std::tan(fov/2.0); } /** * Test a point against the viewing frustrum * @return True if within frustrum */ bool frustrum::test_point(const point3d& p) { if (p.z <= k*p.x && k*p.x <= -p.z && p.y >= p.z && -p.z >= p.y) { return true; } return false; } /** * Test a patch against the viewing frustrum. Even if all the * points are outside, part of the patch may be visible. * @return True if at least part of patch lies within frustrum. */ bool frustrum::test_patch(const point3d p[4]) { int flags[4] = {0, 0, 0, 0}; for (int i=0; i<4; i++) { if (p[i].z < far) flags[i] |= BEHIND; if (p[i].z > near) flags[i] |= INFRONT; if (k*p[i].x < p[i].z) flags[i] |= LEFT; if (k*p[i].x > -p[i].z) flags[i] |= RIGHT; // @todo Apply 'k' to next two. if (p[i].y < p[i].z) flags[i] |= ABOVE; if (p[i].y > -p[i].z) flags[i] |= BELOW; } // If bitwise AND has at least one '1', then all points are // in the same out-of-frustrum region. if (flags[0] & flags[1] & flags[2] & flags[3]) { return false; } return true; }