geom: add simple frustum class
This commit is contained in:
parent
47efd293c9
commit
b1276519ef
@ -205,6 +205,8 @@ list (
|
|||||||
geom/cylinder.hpp
|
geom/cylinder.hpp
|
||||||
geom/ellipse.cpp
|
geom/ellipse.cpp
|
||||||
geom/ellipse.hpp
|
geom/ellipse.hpp
|
||||||
|
geom/frustum.cpp
|
||||||
|
geom/frustum.hpp
|
||||||
geom/iostream.cpp
|
geom/iostream.cpp
|
||||||
geom/iostream.hpp
|
geom/iostream.hpp
|
||||||
geom/ops.hpp
|
geom/ops.hpp
|
||||||
@ -450,6 +452,7 @@ if (TESTS)
|
|||||||
format
|
format
|
||||||
geom/aabb
|
geom/aabb
|
||||||
geom/ray
|
geom/ray
|
||||||
|
geom/frustum
|
||||||
hash/checksum
|
hash/checksum
|
||||||
hash/crc
|
hash/crc
|
||||||
hash/fasthash
|
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
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
*
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_GEOM_FWD_HPP
|
#ifndef CRUFT__UTIL_GEOM_FWD_HPP
|
||||||
#define __UTIL_GEOM_FWD_HPP
|
#define CRUFT__UTIL_GEOM_FWD_HPP
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
@ -28,6 +28,8 @@ namespace util::geom {
|
|||||||
template <size_t S, typename T> struct rect;
|
template <size_t S, typename T> struct rect;
|
||||||
template <size_t S, typename T> struct cylinder;
|
template <size_t S, typename T> struct cylinder;
|
||||||
template <size_t S, typename T> struct tri;
|
template <size_t S, typename T> struct tri;
|
||||||
|
|
||||||
|
template <typename T> struct frustum;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
*
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "iostream.hpp"
|
#include "iostream.hpp"
|
||||||
|
|
||||||
#include "sphere.hpp"
|
#include "sphere.hpp"
|
||||||
|
#include "plane.hpp"
|
||||||
|
#include "frustum.hpp"
|
||||||
#include "../coord/iostream.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<2,float>);
|
||||||
template std::ostream& util::geom::operator<< (std::ostream&, util::geom::sphere<3,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
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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
|
#ifndef CRUFT_UTIL_GEOM_IOSTREAM_HPP
|
||||||
#define __UTIL_GEOM_IOSTREAM_HPP
|
#define CRUFT_UTIL_GEOM_IOSTREAM_HPP
|
||||||
|
|
||||||
#include "fwd.hpp"
|
#include "fwd.hpp"
|
||||||
|
|
||||||
@ -35,6 +35,14 @@ namespace util::geom {
|
|||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<< (std::ostream&, sphere<S,T>);
|
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
|
#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