geom: add simple frustum class
This commit is contained in:
parent
47efd293c9
commit
b1276519ef
@ -205,6 +205,8 @@ list (
|
||||
geom/cylinder.hpp
|
||||
geom/ellipse.cpp
|
||||
geom/ellipse.hpp
|
||||
geom/frustum.cpp
|
||||
geom/frustum.hpp
|
||||
geom/iostream.cpp
|
||||
geom/iostream.hpp
|
||||
geom/ops.hpp
|
||||
@ -450,6 +452,7 @@ if (TESTS)
|
||||
format
|
||||
geom/aabb
|
||||
geom/ray
|
||||
geom/frustum
|
||||
hash/checksum
|
||||
hash/crc
|
||||
hash/fasthash
|
||||
|
68
geom/frustum.cpp
Normal file
68
geom/frustum.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "frustum.hpp"
|
||||
|
||||
using util::geom::frustum;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
frustum<T>::frustum (const matrix4<T> &transform)
|
||||
{
|
||||
// left
|
||||
planes[0].coefficients[0] = transform[3][0] + transform[0][0];
|
||||
planes[0].coefficients[1] = transform[3][1] + transform[0][1];
|
||||
planes[0].coefficients[2] = transform[3][2] + transform[0][2];
|
||||
planes[0].coefficients[3] = transform[3][3] + transform[0][3];
|
||||
|
||||
// Right clipping plane
|
||||
planes[1].coefficients[0] = transform[3][0] - transform[0][0];
|
||||
planes[1].coefficients[1] = transform[3][1] - transform[0][1];
|
||||
planes[1].coefficients[2] = transform[3][2] - transform[0][2];
|
||||
planes[1].coefficients[3] = transform[3][3] - transform[0][3];
|
||||
|
||||
// Top clipping plane
|
||||
planes[2].coefficients[0] = transform[3][0] - transform[1][0];
|
||||
planes[2].coefficients[1] = transform[3][1] - transform[1][1];
|
||||
planes[2].coefficients[2] = transform[3][2] - transform[1][2];
|
||||
planes[2].coefficients[3] = transform[3][3] - transform[1][3];
|
||||
|
||||
// Bottom clipping plane
|
||||
planes[3].coefficients[0] = transform[3][0] + transform[1][0];
|
||||
planes[3].coefficients[1] = transform[3][1] + transform[1][1];
|
||||
planes[3].coefficients[2] = transform[3][2] + transform[1][2];
|
||||
planes[3].coefficients[3] = transform[3][3] + transform[1][3];
|
||||
|
||||
// Near clipping plane
|
||||
planes[4].coefficients[0] = transform[3][0] + transform[2][0];
|
||||
planes[4].coefficients[1] = transform[3][1] + transform[2][1];
|
||||
planes[4].coefficients[2] = transform[3][2] + transform[2][2];
|
||||
planes[4].coefficients[3] = transform[3][3] + transform[2][3];
|
||||
|
||||
// Far clipping plane
|
||||
planes[5].coefficients[0] = transform[3][0] - transform[2][0];
|
||||
planes[5].coefficients[1] = transform[3][1] - transform[2][1];
|
||||
planes[5].coefficients[2] = transform[3][2] - transform[2][2];
|
||||
planes[5].coefficients[3] = transform[3][3] - transform[2][3];
|
||||
|
||||
for (auto &p: planes)
|
||||
p = normalised (p);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template struct util::geom::frustum<float>;
|
68
geom/frustum.hpp
Normal file
68
geom/frustum.hpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef CRUFT_UTIL_GEOM_FRUSTUM_HPP
|
||||
#define CRUFT_UTIL_GEOM_FRUSTUM_HPP
|
||||
|
||||
#include "../matrix.hpp"
|
||||
#include "plane.hpp"
|
||||
#include "aabb.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace util::geom {
|
||||
/// a viewing frustrum comprised of 4 axis planes, a near plane, and a far
|
||||
/// plane. it may describe something other than a perspective projection
|
||||
/// (eg, an orthographic projection)
|
||||
template <typename ValueT>
|
||||
struct frustum {
|
||||
explicit frustum (const matrix<4,4,ValueT>&);
|
||||
|
||||
std::array<plane<3,ValueT>, 6> planes;
|
||||
};
|
||||
|
||||
using frustum3f = frustum<float>;
|
||||
|
||||
|
||||
/// tests whether a frustum and an aabb overlap
|
||||
///
|
||||
/// XXX: there may be occasional false positives.
|
||||
template <size_t S, typename T>
|
||||
bool
|
||||
intersects (const frustum<T> &f, const aabb<S,T> &b)
|
||||
{
|
||||
for (const auto &p: f.planes) {
|
||||
const auto n = normal (p);
|
||||
const auto positive = n > 0;
|
||||
|
||||
const auto lo = select (positive, b.lo, b.hi);
|
||||
const auto hi = select (positive, b.hi, b.lo);
|
||||
|
||||
if (dot (n, lo) + p.coefficients[S] > 0)
|
||||
return false; // OUTSIDE
|
||||
|
||||
if (dot (n, hi) + p.coefficients[S] >= 0)
|
||||
return true; //INTERSECT
|
||||
}
|
||||
|
||||
// INSIDE
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@ -11,11 +11,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
* Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_GEOM_FWD_HPP
|
||||
#define __UTIL_GEOM_FWD_HPP
|
||||
#ifndef CRUFT__UTIL_GEOM_FWD_HPP
|
||||
#define CRUFT__UTIL_GEOM_FWD_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
@ -28,6 +28,8 @@ namespace util::geom {
|
||||
template <size_t S, typename T> struct rect;
|
||||
template <size_t S, typename T> struct cylinder;
|
||||
template <size_t S, typename T> struct tri;
|
||||
|
||||
template <typename T> struct frustum;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -11,12 +11,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "iostream.hpp"
|
||||
|
||||
#include "sphere.hpp"
|
||||
#include "plane.hpp"
|
||||
#include "frustum.hpp"
|
||||
#include "../coord/iostream.hpp"
|
||||
|
||||
|
||||
@ -32,3 +34,30 @@ util::geom::operator<< (std::ostream &os, util::geom::sphere<S,T> s)
|
||||
//-----------------------------------------------------------------------------
|
||||
template std::ostream& util::geom::operator<< (std::ostream&, util::geom::sphere<2,float>);
|
||||
template std::ostream& util::geom::operator<< (std::ostream&, util::geom::sphere<3,float>);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
std::ostream&
|
||||
util::geom::operator<< (std::ostream &os, plane<S,T> val)
|
||||
{
|
||||
return os << val.coefficients;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template std::ostream& util::geom::operator<< (std::ostream&, plane<2,float>);
|
||||
template std::ostream& util::geom::operator<< (std::ostream&, plane<3,float>);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
std::ostream&
|
||||
util::geom::operator<< (std::ostream &os, frustum<T> val)
|
||||
{
|
||||
return os << "[ " << util::make_infix (val.planes) << " ]";
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template std::ostream& util::geom::operator<< (std::ostream&, frustum<float>);
|
||||
|
@ -11,11 +11,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
||||
* Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_GEOM_IOSTREAM_HPP
|
||||
#define __UTIL_GEOM_IOSTREAM_HPP
|
||||
#ifndef CRUFT_UTIL_GEOM_IOSTREAM_HPP
|
||||
#define CRUFT_UTIL_GEOM_IOSTREAM_HPP
|
||||
|
||||
#include "fwd.hpp"
|
||||
|
||||
@ -35,6 +35,14 @@ namespace util::geom {
|
||||
template <size_t S, typename T>
|
||||
std::ostream&
|
||||
operator<< (std::ostream&, sphere<S,T>);
|
||||
|
||||
template <size_t S, typename T>
|
||||
std::ostream&
|
||||
operator<< (std::ostream&, plane<S,T>);
|
||||
|
||||
template <typename T>
|
||||
std::ostream&
|
||||
operator<< (std::ostream&, frustum<T>);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
35
test/geom/frustum.cpp
Normal file
35
test/geom/frustum.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "tap.hpp"
|
||||
|
||||
#include "geom/frustum.hpp"
|
||||
#include "geom/aabb.hpp"
|
||||
#include "matrix.hpp"
|
||||
|
||||
#include "geom/iostream.hpp"
|
||||
#include <iostream>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
main ()
|
||||
{
|
||||
util::TAP::logger tap;
|
||||
|
||||
const util::geom::frustum3f origin90 (
|
||||
util::perspective (90.f, 1.f, {0.01f, 1.f})
|
||||
);
|
||||
|
||||
static const struct {
|
||||
util::geom::aabb3f box;
|
||||
bool intersects;
|
||||
const char *message;
|
||||
} TESTS[] = {
|
||||
{ { { -1, -1, -1 }, { 1, 1, 1 } }, true, "covers origin with unit radius" },
|
||||
{ { { -9, -9, -9 }, { -8, -8, -8 } }, false, "out of view negative" },
|
||||
{ { { -1, -1, 2 }, { 1, 1, 3 } }, false, "past far plane" },
|
||||
};
|
||||
|
||||
for (const auto &t: TESTS) {
|
||||
tap.expect_eq (intersects (origin90, t.box), t.intersects, "origin frustrum, %s", t.message);
|
||||
}
|
||||
|
||||
return tap.status ();
|
||||
};
|
Loading…
Reference in New Issue
Block a user