Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef AABB_H
- #define AABB_H
- #include <math/Log2Math.h>
- #include <array>
- #include <vector>
- #include <iostream>
- #include <limits>
- #include <Vertex.h>
- #include <math/MathHelpers.h>
- #include <ContributionResult.h>
- namespace Log2
- {
- class Mesh;
- class Model;
- template<unsigned Dim, typename T>
- class AABB
- {
- public:
- using Vector = Vector<Dim, T>;
- using Matrix = Matrix<Dim + 1, Dim + 1, T>;
- using Type = T;
- static auto constexpr getDim() { return Dim; }
- static const auto NUM_VERTS = 1 << Dim;
- AABB() = default;
- AABB(AABB const & other) = default;
- AABB& operator=(AABB const & other) = default;
- ~AABB() = default;
- AABB(Vector const & min, Vector const & max) :
- _min(min),
- _max(max)
- {}
- explicit AABB(Model const & model)
- {
- for (auto const & m : model.meshes()) {
- unify(m->aabb());
- }
- }
- explicit AABB(Mesh const & mesh) :
- AABB(mesh.vertices().begin(), mesh.vertices().end())
- {
- }
- AABB(Vertex const * begin, Vertex const * const end)
- {
- while (begin != end) {
- update((begin++)->position());
- }
- }
- AABB(AABB const & other, const Matrix & transform)
- {
- ComputeFromTransform<NUM_VERTS - 1>::call(transform, other, *this);
- }
- AABB(Vector const * begin, Vector const * const end)
- {
- while (begin != end) {
- update(*begin++);
- }
- }
- auto const & min() const
- {
- return _min;
- }
- auto const & max() const
- {
- return _max;
- }
- auto & min()
- {
- return _min;
- }
- auto & max()
- {
- return _max;
- }
- auto update(Vector const & vec)
- {
- _min.minimize(vec);
- _max.maximize(vec);
- }
- auto contains(AABB const & other) const
- {
- return _min <= other._min && _max >= other._max;
- }
- auto fullyContains(AABB const & other) const
- {
- return _min < other._min && _max > other._max;
- }
- auto contains(Vector const & p) const
- {
- return _min <= p && _max >= p;
- }
- auto fullyContains(Vector const & p) const
- {
- return _min < p && _max > p;
- }
- auto intersects(AABB const & other) const
- {
- return _max >= other._min && _min <= other._max;
- }
- auto intersects(AABB const & moving, Vector const & v, Vector const & v_inv, T& t_first) const
- {
- t_first = static_cast<T>(0);
- auto t_last = static_cast<T>(1);
- return intersects(moving) || IntersectMoving<>::call(*this, moving, v, v_inv, t_first, t_last);
- }
- template<unsigned i = Dim - 1u>
- struct IntersectMoving
- {
- static auto call(AABB const & a, AABB const & b, Vector const & v, Vector const & v_inv, T& t_first, T& t_last)
- {
- if (v.at<i>() == static_cast<T>(0) && (b._min.at<i>() > a._max.at<i>() || b._max.at<i>() < a._min.at<i>())) {
- return false;
- }
- else if (v.at<i>() < static_cast<T>(0)) {
- if (b._max.at<i>() < a._min.at<i>()) return false;
- if (a._max.at<i>() < b._min.at<i>()) Algorithm::maximize((a._max.at<i>() - b._min.at<i>()) * v_inv.at<i>(), t_first);
- if (b._max.at<i>() > a._min.at<i>()) Algorithm::minimize((a._min.at<i>() - b._max.at<i>()) * v_inv.at<i>(), t_last);
- }
- else {
- if (b._min.at<i>() > a._max.at<i>()) return false;
- if (b._max.at<i>() < a._min.at<i>()) Algorithm::maximize((a._min.at<i>() - b._max.at<i>()) * v_inv.at<i>(), t_first);
- if (a._max.at<i>() > b._min.at<i>()) Algorithm::minimize((a._max.at<i>() - b._min.at<i>()) * v_inv.at<i>(), t_last);
- }
- return t_first <= t_last && IntersectMoving<i - 1u>::call(a, b, v, v_inv, t_first, t_last);
- }
- };
- template<>
- struct IntersectMoving<0>
- {
- static auto call(AABB const & a, AABB const & b, Vector const & v, Vector const & v_inv, T& t_first, T& t_last)
- {
- if (v.at<0>() == static_cast<T>(0) && (b._min.at<0>() > a._max.at<0>() || b._max.at<0>() < a._min.at<0>())) {
- return false;
- }
- else if (v.at<0>() < static_cast<T>(0)) {
- if (b._max.at<0>() < a._min.at<0>()) return false;
- if (a._max.at<0>() < b._min.at<0>()) Algorithm::maximize((a._max.at<0>() - b._min.at<0>()) * v_inv.at<0>(), t_first);
- if (b._max.at<0>() > a._min.at<0>()) Algorithm::minimize((a._min.at<0>() - b._max.at<0>()) * v_inv.at<0>(), t_last);
- }
- else {
- if (b._min.at<0>() > a._max.at<0>()) return false;
- if (b._max.at<0>() < a._min.at<0>()) Algorithm::maximize((a._min.at<0>() - b._max.at<0>()) * v_inv.at<0>(), t_first);
- if (a._max.at<0>() > b._min.at<0>()) Algorithm::minimize((a._max.at<0>() - b._min.at<0>()) * v_inv.at<0>(), t_last);
- }
- return t_first <= t_last;
- }
- };
- auto union_(AABB const & other) const
- {
- return AABB(minimum(_min, other._min), maximum(_max, other._max));
- }
- auto intersection(AABB const & other) const
- {
- return AABB(maximum(_min, other._min), minimum(_max, other._max));
- }
- auto& unify(AABB const & other)
- {
- _min.minimize(other._min);
- _max.maximize(other._max);
- return *this;
- }
- auto& intersect(AABB const & other)
- {
- _min.maximize(other._min);
- _max.minimize(other._max);
- return *this;
- }
- auto valid() const
- {
- return _max >= _min;
- }
- auto minVec(Vector const & p) const
- {
- return _min - p;
- }
- auto maxVec(Vector const & p) const
- {
- return p - _max;
- }
- auto distToBorderForPointInside(Vector const & p) const
- {
- return std::min(minReduce(abs(minVec(p))), minReduce(abs(maxVec(p))));
- }
- auto distToBorder(Vector const & p) const
- {
- return contains(p) ? distToBorderForPointInside(p) : std::sqrt(minSquaredDist(p));
- }
- auto cost(AABB const & other) const
- {
- return union_(other).squaredSize() - squaredSize();
- }
- auto vertices() const
- {
- std::array<Vector, NUM_VERTS> vertices;
- FillArray<NUM_VERTS - 1>::call(*this, vertices);
- return vertices;
- }
- template<unsigned count>
- static auto fromTransform(Vector const * first, Matrix const & transform)
- {
- Vector verts[count];
- FillVerts<count - 1u>::call(first, transform, verts);
- return fromVertices<count>(verts);
- }
- template<unsigned i>
- struct FillVerts
- {
- static auto call(Vector const * first, Matrix const & transform, Vector* res)
- {
- *(res + i) = (transform * (first + i)->toHomogeneous()).homogeneousDivide().reduce<Dim>();
- FillVerts<i - 1u>::call(first, transform, res);
- }
- };
- template<>
- struct FillVerts<0>
- {
- static auto call(Vector const * first, Matrix const & transform, Vector* res)
- {
- *res = (transform * first->toHomogeneous()).homogeneousDivide().reduce<Dim>();
- }
- };
- template<unsigned count>
- static auto fromVertices(Vector const * first)
- {
- AABB ret;
- ComputeFromVertices<count - 1>::call(first, ret);
- return ret;
- }
- auto centerTimesTwo() const
- {
- return _min + _max;
- }
- auto center() const
- {
- return centerTimesTwo() * static_cast<T>(0.5);
- }
- auto center(unsigned const & axis) const
- {
- return (_min[axis] + _max[axis]) * static_cast<T>(0.5);
- }
- template<unsigned axis>
- auto center() const
- {
- return (_min.at<axis>() + _max.at<axis>()) * static_cast<T>(0.5);
- }
- auto extent() const
- {
- return _max - _min;
- }
- auto halfExtent(Vector const & center) const
- {
- return _max - center;
- }
- auto halfExtent() const
- {
- return extent() * static_cast<T>(0.5);
- }
- struct CenterExtent
- {
- Vector _center;
- Vector _halfExtent;
- };
- CenterExtent centerExtent() const
- {
- auto c = center();
- return { c, halfExtent(c) };
- }
- auto size() const
- {
- return extent().length();
- }
- auto squaredSize() const
- {
- return extent().squaredLength();
- }
- auto largerThan(AABB const & other) const
- {
- return squaredSize() > other.squaredSize();
- }
- auto volume() const
- {
- return extent().volume();
- }
- auto closestPoint(Vector const & point) const
- {
- return clamp(point, _min, _max);
- }
- template<unsigned index>
- auto squaredDistToVertex(Vector const & point) const
- {
- static_assert(index < NUM_VERTS, "Invalid index");
- return squaredDistance(point, getVertex<index>());
- }
- auto minSquaredDist(Vector const & point) const
- {
- auto dist = static_cast<T>(0);
- ComputeMinSquaredDist<>::call(*this, point, dist);
- return dist;
- }
- auto maxSquaredDist(Vector const & point) const
- {
- return maxSquaredDist(minVec(point), maxVec(point));
- }
- static_assert(std::numeric_limits<float>::is_iec559, "Division by zero not supported on this platform.");
- template<typename T>
- auto contributes(Vector const & cam_pos, T const & thresh, T const & max_squared_size) const
- {
- return max_squared_size / minSquaredDist(cam_pos) > thresh;
- }
- template<typename T>
- auto contributes(Vector const & cam_pos, T const & thresh) const
- {
- return contributes(cam_pos, thresh, squaredSize());
- }
- template<typename T>
- auto fullyContributes(Vector const & cam_pos, T const & thresh, T const & min_squared_size) const
- {
- return min_squared_size / maxSquaredDist(cam_pos) > thresh;
- }
- template<typename T>
- auto fullyContributes(Vector const & cam_pos, T const & thresh) const
- {
- return fullyContributes(cam_pos, thresh, squaredSize());
- }
- template<typename T>
- ContribResult computeContribution(Vector const & cam_pos, T const & thresh, T const & min_squared_size, T const & max_squared_size) const
- {
- auto min_vec = minVec(cam_pos);
- auto max_vec = maxVec(cam_pos);
- if (max_squared_size / minSquaredDist(cam_pos, min_vec, max_vec) > thresh) {
- return min_squared_size / maxSquaredDist(min_vec, max_vec) > thresh ? ContributionResult::INSIDE : ContributionResult::INTERSECTING;
- }
- return ContributionResult::OUTSIDE;
- }
- auto vertex(unsigned const & index) const
- {
- return Vector(index & 4 ? _min.at<0>() : _max.at<0>(),
- index & 2 ? _min.at<1>() : _max.at<1>(),
- index & 1 ? _min.at<2>() : _max.at<2>());
- }
- template<unsigned index>
- auto vertex() const
- {
- return Vector(index & 4 ? _min.at<0>() : _max.at<0>(),
- index & 2 ? _min.at<1>() : _max.at<1>(),
- index & 1 ? _min.at<2>() : _max.at<2>());
- }
- auto longestAxis() const
- {
- return extent().longestAxis();
- }
- friend auto& operator << (std::ostream& os, AABB const & aabb)
- {
- os << "AABB [ " << aabb.min() << " " << aabb.max() << " ]";
- return os;
- }
- static auto minMemOffset() { return offsetof(AABB, _min); }
- static auto maxMemOffset() { return offsetof(AABB, _max); }
- private:
- Vector _min = std::numeric_limits<T>::max();
- Vector _max = std::numeric_limits<T>::lowest();
- template<unsigned index>
- struct ComputeFromTransform
- {
- static auto call(Matrix const & transform, AABB const & other, AABB& res)
- {
- res.update((transform * other.vertex<index>().toHomogeneous()).reduce<Dim>());
- ComputeFromTransform<index - 1>::call(transform, other, res);
- }
- };
- template<>
- struct ComputeFromTransform<0>
- {
- static auto call(Matrix const & transform, AABB const & other, AABB& res)
- {
- res.update((transform * other.vertex<0>().toHomogeneous()).reduce<Dim>());
- }
- };
- template<unsigned index>
- struct FillArray
- {
- static auto call(AABB const & aabb, std::array<Vector, NUM_VERTS>& res)
- {
- res[index] = aabb.vertex<index>();
- FillArray<index - 1>::call(aabb, res);
- }
- };
- template<>
- struct FillArray<0>
- {
- static auto call(AABB const & aabb, std::array<Vector, NUM_VERTS>& res)
- {
- res[0] = aabb.vertex<0>();
- }
- };
- template<unsigned index>
- struct ComputeFromVertices
- {
- static auto call(Vector const * first, AABB& res)
- {
- res.update(*(first + index));
- ComputeFromVertices<index - 1>::call(first, res);
- }
- };
- template<>
- struct ComputeFromVertices<0>
- {
- static auto call(Vector const * first, AABB& res)
- {
- res.update(*first);
- }
- };
- template<unsigned index = Dim - 1>
- struct ComputeMinSquaredDist
- {
- static auto call(AABB const & aabb, Vector const & point, T& dist)
- {
- if (point.at<index>() < aabb._min.at<index>()) {
- dist += MathHelpers::pow<2>(aabb._min.at<index>() - point.at<index>());
- }
- else if (point.at<index>() > aabb._max.at<index>()) {
- dist += MathHelpers::pow<2>(point.at<index>() - aabb._max.at<index>());
- }
- ComputeMinSquaredDist<index - 1>::call(aabb, point, dist);
- }
- static auto call(AABB const & aabb, Vector const & point, Vector const & min_vec, Vector const & max_vec, T& dist)
- {
- if (min_vec.at<index>() > static_cast<T>(0)) {
- dist += MathHelpers::pow<2>(min_vec.at<index>());
- }
- else if (max_vec.at<index>() > static_cast<T>(0)) {
- dist += MathHelpers::pow<2>(max_vec.at<index>());
- }
- ComputeMinSquaredDist<index - 1>::call(aabb, point, min_vec, max_vec, dist);
- }
- };
- template<>
- struct ComputeMinSquaredDist<0>
- {
- static auto call(AABB const & aabb, Vector const & point, T& dist)
- {
- if (point.at<0>() < aabb._min.at<0>()) {
- dist += MathHelpers::pow<2>(aabb._min.at<0>() - point.at<0>());
- }
- else if (point.at<0>() > aabb._max.at<0>()) {
- dist += MathHelpers::pow<2>(point.at<0>() - aabb._max.at<0>());
- }
- }
- static auto call(AABB const & aabb, Vector const & point, Vector const & min_vec, Vector const & max_vec, T& dist)
- {
- if (min_vec.at<0>() > static_cast<T>(0)) {
- dist += MathHelpers::pow<2>(min_vec.at<0>());
- }
- else if (max_vec.at<0>() > static_cast<T>(0)) {
- dist += MathHelpers::pow<2>(max_vec.at<0>());
- }
- }
- };
- auto minSquaredDist(Vector const & point, Vector const & min_vec, Vector const & max_vec) const
- {
- auto dist = static_cast<T>(0);
- ComputeMinSquaredDist<>::call(*this, point, min_vec, max_vec, dist);
- return dist;
- }
- auto maxSquaredDist(Vector const & min_vec, Vector const & max_vec) const
- {
- return maximum(abs(min_vec), abs(max_vec)).squaredLength();
- }
- };
- using AABB2f = AABB<2, float>;
- using AABB3f = AABB<3, float>;
- using AABB4f = AABB<4, float>;
- using AABB2i = AABB<2, int>;
- using AABB3i = AABB<3, int>;
- using AABB4i = AABB<4, int>;
- using AABB2u = AABB<2, unsigned>;
- using AABB3u = AABB<3, unsigned>;
- using AABB4u = AABB<4, unsigned>;
- }
- #endif // !AABB_H
- #ifndef ALGORITHM_H
- #define ALGORITHM_H
- #include <functional>
- #include <type_traits>
- namespace Log2
- {
- class Algorithm
- {
- public:
- Algorithm() = delete;
- template<typename T>
- static auto ptrDiff(T const * const begin, T const * const end)
- {
- return end - begin;
- }
- template<typename T>
- static auto midPtr(T* const begin, long long const & ptr_diff)
- {
- return begin + ptr_diff / 2u;
- }
- template<typename T>
- static auto midPtr(T* const begin, T* const end)
- {
- return midPtr(begin, ptrDiff(begin, end));
- }
- static auto continueSplit(long long const & ptr_diff)
- {
- return ptr_diff > 1u;
- }
- template<typename T>
- static auto continueSplit(T const * const begin, T const * const end)
- {
- return continueSplit(ptrDiff(begin, end));
- }
- template<typename T>
- static auto swap(T& a, T& b)
- {
- auto temp = a;
- a = b;
- b = temp;
- }
- template<typename T, typename Pred>
- static auto partition(T* begin, T const * const end, Pred&& pred)
- {
- auto* mid = begin;
- while (begin != end) {
- if (pred(*begin)) {
- swap(*begin, *mid++);
- }
- ++begin;
- }
- return mid;
- }
- template<typename T>
- static auto isPalindrom(T const * begin, T const * end)
- {
- return isPalindrom(begin, end, std::equal_to<T>());
- }
- template<typename T, typename Pred>
- static auto isPalindrom(T const * begin, T const * end, Pred&& pred)
- {
- auto const * const mid = midPtr(begin, end);
- while (begin != mid && end != mid) {
- if (!pred(*begin++, *(--end))) {
- return false;
- }
- }
- return true;
- }
- template<typename T>
- static auto compare(T const * a, T const * b, size_t len)
- {
- return compare(a, b, len, std::equal_to<T>());
- }
- template<typename T, typename Comp>
- static auto compare(T const * a, T const * b, size_t len, Comp&& comp)
- {
- auto const * const end = a + len;
- while (a != end) {
- if (!comp(*a++, *b++)) {
- return false;
- }
- }
- return true;
- }
- /**
- * Same as partition, but returns the midpoint if the range cannot be split based on pred.
- */
- template<typename T, typename Pred>
- static auto partitionForceSplit(T* const begin, T* const end, Pred&& pred)
- {
- auto* const mid = partition(begin, end, pred);
- return mid == begin || mid == end ? midPtr(begin, end) : mid;
- }
- /**
- * Update peak
- */
- template<typename T, typename Type>
- static void updatePeak(T const & prev_peak_val, Type& peak, T const & val, Type const & data)
- {
- updatePeak(prev_peak_val, peak, val, data, std::less<T>());
- }
- template<typename T, typename Type, typename Compare>
- static void updatePeak(T const & prev_peak_val, Type& peak, T const & val, Type const & data, Compare&& comp)
- {
- if (comp(val, prev_peak_val)) {
- peak = data;
- }
- }
- template<typename T>
- static auto minimize(const T& other, T& out)
- {
- out = std::min(out, other);
- }
- template<typename T>
- static auto maximize(const T& other, T& out)
- {
- out = std::max(out, other);
- }
- template<typename T>
- static auto mergeSort(T* const begin, T* const end)
- {
- mergeSort(begin, end, std::less<T>());
- }
- template<typename T, typename Compare>
- static auto mergeSort(T* const begin, T* const end, Compare&& comp)
- {
- auto ptr_diff = ptrDiff(begin, end);
- if (ptr_diff) {
- auto* temp = new T[ptr_diff];
- mergeSort(begin, end, temp, comp);
- delete[] temp;
- }
- }
- template<typename T>
- static auto copyRange(T const * begin, T const * const end, T* dst)
- {
- copyRangeOverwrite(begin, end, dst);
- }
- template<typename T>
- static auto copyRangeOverwrite(T const * begin, T const * const end, T*& dst)
- {
- while (begin != end) {
- *dst++ = *begin++;
- }
- }
- template<typename T>
- static void quickSortLessEqual(T* const begin, T* const end)
- {
- quickSort(begin, end, std::less_equal<T>());
- }
- template<typename T>
- static void quickSortGreaterEqual(T* const begin, T* const end)
- {
- quickSort(begin, end, std::greater_equal<T>());
- }
- template<typename T>
- struct DefaultVal
- {
- auto const & operator() (T const & t) { return t; }
- };
- template<typename T>
- static auto mean(T const* begin, T const * const end)
- {
- return mean(begin, end, DefaultVal<T>());
- }
- template<typename T, typename GetVal, typename RetVal = float>
- static auto mean(T const* begin, T const * const end, GetVal&& get_val)
- {
- static_assert(std::is_same<RetVal, float>::value || std::is_same<RetVal, double>::value, "RetVal must be float or double");
- auto const denom = static_cast<RetVal>(end - begin);
- auto res = get_val(*begin++) / denom;
- while (begin != end) {
- res += get_val(*begin++) / denom;
- }
- return res;
- }
- template<typename T, unsigned index>
- struct Copy
- {
- static void call(T const * src, T* dst)
- {
- dst[index] = src[index];
- Copy<T, index - 1u>::call(src, dst);
- }
- };
- template<typename T>
- struct Copy<T, 0>
- {
- static void call(T const * src, T* dst)
- {
- *dst = *src;
- }
- };
- private:
- template<typename T, typename Compare>
- static void mergeSort(T* const begin, T* const end, T* temp, Compare&& comp)
- {
- auto ptr_diff = ptrDiff(begin, end);
- if (continueSplit(ptr_diff)) {
- auto * const mid = midPtr(begin, ptr_diff);
- mergeSort(begin, mid, temp, comp);
- mergeSort(mid, end, temp, comp);
- merge(begin, mid, end, temp, comp);
- }
- }
- template<typename T, typename Compare>
- static auto merge(T* begin, T const * const mid, T const * const end, T* temp, Compare&& comp)
- {
- copyRange(begin, end, temp);
- auto* right_temp = temp + ptrDiff(begin, mid);
- auto const * const left_temp_end = right_temp;
- auto const * const right_temp_end = temp + ptrDiff(begin, end);
- mergeResults(temp, right_temp, right_temp_end, begin, comp);
- copyRangeOverwrite(temp, left_temp_end, begin);
- copyRangeOverwrite(right_temp, right_temp_end, begin);
- }
- template<typename T, typename Compare>
- static auto mergeResults(T*& begin, T*& mid, T const * const end, T*& dst, Compare&& comp)
- {
- auto const * const mid_ptr = mid;
- while (begin != mid_ptr && mid != end) {
- *dst++ = comp(*begin, *mid) ? *begin++ : *mid++;
- }
- }
- template<typename T, typename Compare>
- static void quickSort(T* const begin, T* const end, Compare&& comp)
- {
- if (begin < end) {
- auto const pivot = *(end - 1);
- auto* const mid = partition(begin, end, [&](const T& a) {
- return comp(a, pivot);
- });
- quickSort(begin, mid - 1, comp);
- quickSort(mid, end, comp);
- }
- }
- };
- }
- #endif // !ALGORITHM_H
- #ifndef BOUNDINGVOLUMEHIERARCHY_H
- #define BOUNDINGVOLUMEHIERARCHY_H
- #include <CullingParams.h>
- #include <IntersectionTests.h>
- #include <Ray.h>
- #include <boost/pool/object_pool.hpp>
- #include <Algorithm.h>
- #include <functional>
- #include <Primitive.h>
- #include <StackTrivial.h>
- #include <CsmTree.h>
- #include <BVHNode.h>
- #include <BVHNodePool.h>
- namespace Log2
- {
- class BoundingVolumeHierarchy
- {
- public:
- using BV = typename Primitive::BV;
- using Type = typename Primitive::Type;
- using Vector = Vector<BV::getDim(), Type>;
- using Matrix = Matrix<BV::getDim() + 1, BV::getDim() + 1, Type>;
- using Ray = Ray<BV::getDim(), Type>;
- using IntersectRayResult = IntersectRayResult<Type, Matrix>;
- BoundingVolumeHierarchy() = delete;
- BoundingVolumeHierarchy(Primitive * const * begin, Primitive * const * const end) :
- _nodePool(Algorithm::ptrDiff(begin, end))
- {
- StackTrivial<BVHNode::PrimitiveInfo> infos;
- infos.reserve(Algorithm::ptrDiff(begin, end));
- while (begin != end) {
- infos.push_back_unchecked(*begin++);
- }
- _root = _nodePool.createNode(infos);
- }
- BoundingVolumeHierarchy(BoundingVolumeHierarchy const & other) = delete;
- BoundingVolumeHierarchy& operator=(BoundingVolumeHierarchy const & other) = delete;
- BoundingVolumeHierarchy(BoundingVolumeHierarchy&& other) = default;
- BoundingVolumeHierarchy& operator=(BoundingVolumeHierarchy&& other) = default;
- auto cullVisiblePrimitives(CullingParams const & cp, Callback::CbFunc const & on_intersect_frustum, Callback::CbFunc const & on_became_fully_visible, Callback::CbFunc const & on_render) const
- {
- _root->cullVisiblePrimitives(cp, { on_intersect_frustum, on_became_fully_visible, on_render });
- }
- auto cullVisiblePrimitivesWithPlaneMasking(CullingParams const & cp, Callback::CbFunc const & on_intersect_frustum, Callback::CbFunc const & on_became_fully_visible, Callback::CbFunc const & on_render) const
- {
- IntersectedPlanes out(0b11111111);
- _root->cullVisiblePrimitives(cp, out, { on_intersect_frustum, on_became_fully_visible, on_render });
- }
- auto intersectNested(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, std::function<void(Primitive const *)> const & intersect_nested) const
- {
- _root->intersectNested(bv, v, v_inv, min_t_first, intersect_nested);
- }
- auto intersectPrimitives(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, Primitive const *& nearest)
- {
- _root->intersectPrimitives(bv, v, v_inv, min_t_first, nearest);
- }
- auto findNearest(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive const *& nearest, Type& nearest_t, Matrix const *& nearest_transform) const
- {
- _root->findNearest(ray_local, ray_world, transform, nearest, nearest_t, nearest_transform);
- }
- auto findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res) const
- {
- _root->findNearestPrecise(ray_local, ray_world, transform, res);
- }
- auto findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive* parent, IntersectRayResult& res, Primitive*& parent_res) const
- {
- _root->findNearestPrecise(ray_local, ray_world, transform, parent, res, parent_res);
- }
- auto findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res, StackTrivial<BVHNode::NodePtr>& stack) const
- {
- stack.push_back(_root);
- while (stack.size()) {
- stack.pop_back()->findNearestPrecise(ray_local, ray_world, transform, res, stack);
- }
- }
- auto findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested) const
- {
- _root->findNearestNested(ray, res, find_nested);
- }
- auto findNearestNested(Ray const & ray, IntersectRayResult& res, StackTrivial<BVHNode::NodePtr>& stack, std::function<void(Primitive*)> const & find_nested) const
- {
- stack.push_back(_root);
- while (stack.size()) {
- stack.pop_back()->findNearestNested(ray, res, find_nested, stack);
- }
- }
- auto queryRange(BV const & bv, Callback::CbFunc const & cb) const
- {
- _root->queryRange(bv, cb);
- }
- auto queryRange(BV const & bv, CullingParams const & cp, Callback::CbFunc const & cb) const
- {
- _root->queryRange(bv, cp, cb);
- }
- auto sizeInBytes() const
- {
- return _root->sizeInBytes();
- }
- auto sizeInKiloBytes() const
- {
- return static_cast<float>(sizeInBytes()) / 1024.f;
- }
- auto sizeInMegaBytes() const
- {
- return sizeInKiloBytes() / 1024.f;
- }
- auto sizeInGigaBytes() const
- {
- return sizeInMegaBytes() / 1024.f;
- }
- auto bv() const
- {
- return _root->getBV();
- }
- auto const & root() const
- {
- return _root;
- }
- auto countNodes(unsigned& internal_nodes, unsigned& leaf_nodes) const
- {
- internal_nodes = 0;
- leaf_nodes = 0;
- _root->countNodes(internal_nodes, leaf_nodes);
- }
- auto insert(Primitive* const & primitive)
- {
- _root->insert(primitive, _root, _nodePool);
- }
- auto minHeight() const
- {
- return _root->minHeight(0);
- }
- auto maxHeight() const
- {
- return _root->maxHeight(0);
- }
- auto averageHeight() const
- {
- unsigned num_internals, num_leafs;
- countNodes(num_internals, num_leafs);
- auto avg_height = 0.f;
- _root->averageHeight(0.f, 1.f / static_cast<float>(num_leafs), avg_height);
- return avg_height;
- }
- auto remove(Primitive* const & primitive)
- {
- bool deleted = false;
- deleted |= _root->remove(primitive, _root, _nodePool, deleted);
- _root->recalculateDirty();
- return deleted;
- }
- auto removeIfDoesNotFit(Primitive* const & primitive, BV const & bv_old)
- {
- bool deleted = false;
- deleted |= _root->removeIfDoesNotFit(primitive, bv_old, nullptr, _root, _root, _nodePool, deleted);
- _root->recalculateDirty();
- return deleted;
- }
- auto reinsertIfDoesNotFit(Primitive* const & primitive, BV const & bv_old)
- {
- if (removeIfDoesNotFit(primitive, bv_old)) {
- insert(primitive);
- }
- }
- private:
- BVHNodePool _nodePool;
- BVHNode* _root;
- };
- }
- #endif
- #ifndef BVHINTERNALNODE_H
- #define BVHINTERNALNODE_H
- #include <BVHNode.h>
- #include <Descendable.h>
- namespace Log2
- {
- class BVHInternalNode : public BVHNode
- {
- public:
- BVHInternalNode(PrimitiveInfo* const begin, PrimitiveInfo* const end, BVHNodePool& node_pool);
- virtual ~BVHInternalNode() = default;
- virtual void cullVisiblePrimitives(CullingParams const & cp, Callback const & cb) const override;
- virtual void cullVisiblePrimitives(CullingParams const & cp, IntersectedPlanes const & in, Callback const & cb) const override;
- virtual void cullContributingPrimitives(CullingParams const & cp, Callback const & cb) const override;
- virtual void cullAllPrimitives(Callback::CbFunc const & on_render) const override;
- virtual size_t sizeInBytes() const override;
- virtual void intersectNested(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, std::function<void(Primitive const *)> const & intersect_nested) const override;
- virtual void intersectPrimitives(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, Primitive const *& nearest) const override;
- virtual void countNodes(unsigned& internal_nodes, unsigned& leaf_nodes) const override;
- virtual void findNearest(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive const *& nearest, Type& nearest_t, Matrix const *& nearest_transform) const override;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res) override;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive* parent, IntersectRayResult& res, Primitive*& parent_res) override;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res, StackTrivial<NodePtr>& stack) override;
- virtual void findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested) override;
- virtual void findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested, StackTrivial<NodePtr>& stack) override;
- virtual void queryRange(BV const & bv, Callback::CbFunc const & cb) const override;
- virtual void queryRange(BV const & bv, CullingParams const & cp, Callback::CbFunc const & cb) const override;
- virtual void queryContributing(CullingParams const & cp, Callback::CbFunc const & cb) const override;
- virtual void queryAll(Callback::CbFunc const & cb) const override;
- virtual BV getBV() const override;
- virtual Type minSquaredDist(Vector const & point) const override;
- virtual Type dist(Ray const & ray) const override;
- virtual void destroy(BVHNodePool& pool) override;
- virtual Type cost(BV const & bv) const override;
- virtual void insert(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool) override;
- virtual bool remove(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted) override;
- virtual bool removeIfDoesNotFit(PrimitiveInfo const & info, BV const & bv_old, BVHNode const * parent, BVHNode const * root, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted) override;
- virtual void destroyTree(StackTrivial<PrimitiveInfo>& primitives, BVHNodePool& node_pool) override;
- virtual DirtyInfo recalculateDirty() override;
- virtual size_t minHeight(size_t const & height) const override;
- virtual size_t maxHeight(size_t const & height) const override;
- virtual void averageHeight(float const & height, float const & inv_num_leafs, float& avg_height) const override;
- void insert(PrimitiveInfo const & pi);
- NodePtr& childToDescend(BV const & bv);
- void markAsDirty();
- bool isDirty() const;
- void rebuild(NodePtr& this_ptr, NodePtr child, BVHNodePool& node_pool);
- void collectFromChildren(DirtyInfo const & di);
- virtual void descendVisible(Descendable& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendVisible(CsmInternalNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendVisible(CsmLeafNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(Descendable& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(CsmInternalNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(CsmLeafNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendAll(Descendable& other, Callback2::CbFunc const & on_render) override;
- virtual void descendAll(CsmInternalNode& other, Callback2::CbFunc const & on_render) override;
- virtual void descendAll(CsmLeafNode& other, Callback2::CbFunc const & on_render) override;
- void recurseVisible(Descendable& other, CullingParams const & cp, Callback2 const & cb);
- void recurseContributing(Descendable& other, CullingParams const & cp, Callback2 const & cb);
- void recurseAll(Descendable& other, Callback2::CbFunc const & on_render);
- private:
- NodePtr _left, _right;
- BV _bv;
- Type _minSquaredSize, _maxSquaredSize;
- void recurseVisible(CullingParams const & cp, Callback const & cb) const;
- void recurseVisible(CullingParams const & cp, IntersectedPlanes const & ip, Callback const & cb) const;
- void recurseContributing(CullingParams const & cp, Callback const & cb) const;
- void recurseAll(Callback::CbFunc const & on_render) const;
- void recurseNearest(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive const *& nearest, Type& nearest_t, Matrix const *& nearest_transform) const;
- void recurseNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res);
- bool largerThan(BVHInternalNode const & other) const;
- void recurseQueryRange(BV const & bv, Callback::CbFunc const & cb) const;
- void recurseQueryRange(BV const & bv, CullingParams const & cp, Callback::CbFunc const & cb) const;
- void recurseQueryContributing(CullingParams const & cp, Callback::CbFunc const & cb) const;
- void recurseQueryAll(Callback::CbFunc const & cb) const;
- void init(PrimitiveInfo const * begin, PrimitiveInfo const * const end);
- bool contributes(CullingParams const & cp) const;
- bool fullyContributes(CullingParams const & cp) const;
- IntersectResult intersectFrustum(CullingParams const & cp) const;
- IntersectResult intersectFrustum(CullingParams const & cp, IntersectedPlanes const & in, IntersectedPlanes& out) const;
- ContribResult computeContribution(CullingParams const & cp) const;
- };
- }
- #endif
- #ifndef BVHLEAFNODE_H
- #define BVHLEAFNODE_H
- #include <BVHNode.h>
- #include <IntersectionTests.h>
- namespace Log2
- {
- class BVHLeafNode : public BVHNode
- {
- public:
- explicit BVHLeafNode(Primitive* const & primitive);
- virtual ~BVHLeafNode() = default;
- virtual void cullVisiblePrimitives(CullingParams const & cp, Callback const & cb) const override;
- virtual void cullVisiblePrimitives(CullingParams const & cp, IntersectedPlanes const & in, Callback const & cb) const override;
- virtual void cullContributingPrimitives(CullingParams const & cp, Callback const & cb) const override;
- virtual void cullAllPrimitives(Callback::CbFunc const & on_render) const override;
- virtual size_t sizeInBytes() const override;
- virtual void intersectNested(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, std::function<void(Primitive const *)> const & intersect_nested) const override;
- virtual void intersectPrimitives(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, Primitive const *& nearest) const override;
- virtual void countNodes(unsigned& internal_nodes, unsigned& leaf_nodes) const override;
- virtual void findNearest(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive const *& nearest, Type& nearest_t, Matrix const *& nearest_transform) const override;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res) override;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive* parent, IntersectRayResult& res, Primitive*& parent_res) override;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res, StackTrivial<NodePtr>& stack) override;
- virtual void findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested) override;
- virtual void findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested, StackTrivial<NodePtr>& stack) override;
- virtual void queryRange(BV const & bv, Callback::CbFunc const & cb) const override;
- virtual void queryRange(BV const & bv, CullingParams const & cp, Callback::CbFunc const & cb) const override;
- virtual void queryContributing(CullingParams const & cp, Callback::CbFunc const & cb) const override;
- virtual void queryAll(Callback::CbFunc const & cb) const override;
- virtual BV getBV() const override;
- virtual Type minSquaredDist(Vector const & point) const override;
- virtual Type dist(Ray const & ray) const override;
- virtual void destroy(BVHNodePool& pool) override;
- virtual Type cost(BV const & bv) const override;
- virtual void insert(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool) override;
- virtual bool remove(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted) override;
- virtual bool removeIfDoesNotFit(PrimitiveInfo const & info, BV const & bv_old, BVHNode const * parent, BVHNode const * root, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted)override;
- virtual void destroyTree(StackTrivial<PrimitiveInfo>& primitives, BVHNodePool& node_pool) override;
- virtual DirtyInfo recalculateDirty() override;
- virtual size_t minHeight(size_t const & height) const override;
- virtual size_t maxHeight(size_t const & height) const override;
- virtual void averageHeight(float const & height, float const & inv_num_leafs, float& avg_height) const override;
- virtual void descendVisible(Descendable& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendVisible(CsmInternalNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendVisible(CsmLeafNode& other, CullingParams const & cp, Callback2 const & cb)override;
- virtual void descendContributing(Descendable& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(CsmInternalNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(CsmLeafNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendAll(Descendable& other, Callback2::CbFunc const & on_render) override;
- virtual void descendAll(CsmInternalNode& other, Callback2::CbFunc const & on_render) override;
- virtual void descendAll(CsmLeafNode& other, Callback2::CbFunc const & on_render) override;
- private:
- Primitive * _primitive;
- bool contributes(CullingParams const & cp) const;
- IntersectResult intersectFrustum(CullingParams const & cp) const;
- };
- }
- #endif // !BVHLEAFNODE_H
- #ifndef BVHNODE_H
- #define BVHNODE_H
- #include <Primitive.h>
- #include <math/Log2Math.h>
- #include <Callback.h>
- #include <Descendable.h>
- namespace Log2
- {
- class CullingParams;
- class BVHInternalNode;
- class BVHLeafNode;
- class BVHNodePool;
- class Callback;
- class BVHNode : public Descendable
- {
- public:
- using BV = typename Primitive::BV;
- using Ray = typename Primitive::Ray;
- using Matrix = typename Primitive::Matrix;
- using Type = typename Primitive::Type;
- static auto const Dim = BV::getDim();
- using Vector = Vector<Dim, Type>;
- using IntersectRayResult = IntersectRayResult<Type, Matrix>;
- class PrimitiveInfo
- {
- public:
- PrimitiveInfo(Primitive* const & p) :
- _primitive(p),
- _bv(p->bv()),
- _squaredSize(p->squaredSize())
- {
- }
- auto const & primitive() const { return _primitive; }
- auto const & bv() const { return _bv; }
- auto const & squaredSize() const { return _squaredSize; }
- private:
- Primitive* _primitive;
- BV _bv;
- Type _squaredSize;
- };
- class DirtyInfo
- {
- public:
- DirtyInfo(BV const & bv, Type const & min_squared_size, Type const & max_squared_size) :
- _bv(bv),
- _minSquaredSize(min_squared_size),
- _maxSquaredSize(max_squared_size)
- {}
- auto const & bv() const { return _bv; }
- auto const & minSquaredSize() const { return _minSquaredSize; }
- auto const & maxSquaredSize() const { return _maxSquaredSize; }
- private:
- BV _bv;
- Type _minSquaredSize;
- Type _maxSquaredSize;
- };
- using NodePtr = BVHNode * ;
- using CbIntersect = std::function<void(Primitive*, Primitive*)>;
- BVHNode() = default;
- virtual ~BVHNode() = default;
- virtual void cullVisiblePrimitives(CullingParams const & cp, Callback const & cb) const = 0;
- virtual void cullVisiblePrimitives(CullingParams const & cp, IntersectedPlanes const & in, Callback const & cb) const = 0;
- virtual void cullContributingPrimitives(CullingParams const & cp, Callback const & cb) const = 0;
- virtual void cullAllPrimitives(Callback::CbFunc const & on_render) const = 0;
- virtual size_t sizeInBytes() const = 0;
- virtual void intersectNested(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, std::function<void(Primitive const *)> const & intersect_nested) const = 0;
- virtual void intersectPrimitives(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, Primitive const *& nearest) const = 0;
- virtual void countNodes(unsigned& internal_nodes, unsigned& leaf_nodes) const = 0;
- virtual void findNearest(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive const *& nearest, Type& nearest_t, Matrix const *& nearest_transform) const = 0;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res) = 0;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive* parent, IntersectRayResult& res, Primitive*& parent_res) = 0;
- virtual void findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res, StackTrivial<NodePtr>& stack) = 0;
- virtual void findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested) = 0;
- virtual void findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested, StackTrivial<NodePtr>& stack) = 0;
- virtual void queryRange(BV const & bv, Callback::CbFunc const & cb) const = 0;
- virtual void queryRange(BV const & bv, CullingParams const & cp, Callback::CbFunc const & cb) const = 0;
- virtual void queryContributing(CullingParams const & cp, Callback::CbFunc const & cb) const = 0;
- virtual void queryAll(Callback::CbFunc const & cb) const = 0;
- virtual BV getBV() const = 0;
- virtual Type minSquaredDist(const Vector& point) const = 0;
- virtual Type dist(Ray const & ray) const = 0;
- virtual void destroy(BVHNodePool& pool) = 0;
- virtual Type cost(BV const & bv) const = 0;
- virtual void insert(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool) = 0;
- virtual bool remove(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted) = 0;
- virtual bool removeIfDoesNotFit(PrimitiveInfo const & info, BV const & bv_old, BVHNode const * parent, BVHNode const * root, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted) = 0;
- virtual void destroyTree(StackTrivial<PrimitiveInfo>& primitives, BVHNodePool& node_pool) = 0;
- virtual DirtyInfo recalculateDirty() = 0;
- virtual size_t minHeight(size_t const & height) const = 0;
- virtual size_t maxHeight(size_t const & height) const = 0;
- virtual void averageHeight(float const & height, float const & inv_num_leafs, float& avg_height) const = 0;
- };
- }
- #endif
- #ifndef BVHNODEPOOL_H
- #define BVHNODEPOOL_H
- #include <boost/pool/object_pool.hpp>
- #include <BVHNode.h>
- #include <BVHLeafNode.h>
- #include <BVHInternalNode.h>
- namespace Log2
- {
- class BVHNode;
- class BVHNodePool
- {
- public:
- BVHNodePool(size_t num_primitives);
- BVHNodePool(BVHNodePool const & other) = delete;
- BVHNodePool& operator=(BVHNodePool const & other) = delete;
- BVHNodePool(BVHNodePool&& other) = delete;
- BVHNodePool& operator=(BVHNodePool&& other) = delete;
- ~BVHNodePool() = default;
- BVHNode* createInternalNode(BVHNode::PrimitiveInfo* const begin, BVHNode::PrimitiveInfo* const end);
- BVHNode* createLeafNode(Primitive* p);
- BVHNode* createNode(BVHNode::PrimitiveInfo* const begin, BVHNode::PrimitiveInfo* const end);
- BVHNode* createNode(StackTrivial<BVHNode::PrimitiveInfo>& infos);
- void destroy(BVHLeafNode* node);
- void destroy(BVHInternalNode* node);
- private:
- boost::object_pool<BVHInternalNode> _internalNodePool;
- boost::object_pool<BVHLeafNode> _leafNodePool;
- };
- }
- #endif
- #ifndef CSMINTERNALNODE_H
- #define CSMINTERNALNODE_H
- #include <CsmNode.h>
- #include <Primitive.h>
- #include <Descendable.h>
- namespace Log2
- {
- class CsmSplit;
- class CsmNodePool;
- class CsmTree;
- class CsmInternalNode : public CsmNode
- {
- public:
- CsmInternalNode(CsmSplit* begin, CsmSplit* end, CsmTree& np, Matrix<4, 4, Type> const & view_matrix_light);
- ~CsmInternalNode();
- FrustumPlanes<3, Type> const & frustumPlanes() const;
- void recurseVisible(Descendable& other, CullingParams const & cp, Callback2 const & cb);
- void recurseContributing(Descendable& other, CullingParams const & cp, Callback2 const & cb);
- void recurseAll(Descendable& other, Callback2::CbFunc const & on_render);
- BV const & bvRender() const;
- BV const & bvCull() const;
- virtual void descendVisible(Descendable& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendVisible(BVHInternalNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendVisible(BVHLeafNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(Descendable& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(BVHInternalNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(BVHLeafNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendAll(Descendable& other, Callback2::CbFunc const & on_render) override;
- virtual void descendAll(BVHInternalNode& other, Callback2::CbFunc const & on_render) override;
- virtual void descendAll(BVHLeafNode& other, Callback2::CbFunc const & on_render) override;
- private:
- CsmNode* _left;
- CsmNode* _right;
- BV _bvRender;
- BV _bvCull;
- FrustumPlanes<3, Type> _fp;
- };
- }
- #endif
- #ifndef CSMLEAFNODE_H
- #define CSMLEAFNODE_H
- #include <CsmNode.h>
- #include <CsmSplit.h>
- namespace Log2
- {
- class CsmLeafNode : public CsmNode
- {
- public:
- CsmLeafNode(CsmSplit* split);
- virtual void descendVisible(Descendable& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendVisible(BVHInternalNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendVisible(BVHLeafNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(Descendable& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(BVHInternalNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendContributing(BVHLeafNode& other, CullingParams const & cp, Callback2 const & cb) override;
- virtual void descendAll(Descendable& other, Callback2::CbFunc const & on_render) override;
- virtual void descendAll(BVHInternalNode& other, Callback2::CbFunc const & on_render) override;
- virtual void descendAll(BVHLeafNode& other, Callback2::CbFunc const & on_render) override;
- CsmSplit& split();
- private:
- CsmSplit* _split;
- };
- }
- #endif
- #ifndef CSMNODE_H
- #define CSMNODE_H
- #include <Primitive.h>
- #include <Descendable.h>
- namespace Log2
- {
- class CsmNode : public Descendable
- {
- public:
- using Type = Primitive::Type;
- using BV = Primitive::BV;
- };
- }
- #endif // !CSMNODE_H
- #ifndef CSMSPLIT_H
- #define CSMSPLIT_H
- #include <RenderList.h>
- #include <AABB.h>
- #include <Primitive.h>
- #include <FrustumPlanes.h>
- namespace Log2
- {
- class CsmSplit
- {
- using BV = typename Primitive::BV;
- using Type = typename Primitive::Type;
- public:
- CsmSplit(BV const & bv_light_cull, BV const & bv_light_render, Matrix<4, 4, Type> const & view_matrix_light, Matrix<4, 4, Type>* vp);
- CsmSplit() = default;
- CsmSplit(CsmSplit const & other) = default;
- CsmSplit& operator=(CsmSplit const & other) = default;
- BV const & bvCull() const;
- BV const & bvRender() const;
- Matrix<4, 4, Type> const & vp() const;
- FrustumPlanes<3, Type> const & frustumPlanes() const;
- RenderList& renderlist();
- void set(BV const & bv_light_cull, BV const & bv_light_render, Matrix<4, 4, Type> const & view_matrix_light, Matrix<4, 4, Type>* vp);
- private:
- RenderList _rl;
- BV _bvLightCull;
- BV _bvLightRender;
- Matrix<4, 4, Type>* _vp;
- FrustumPlanes<3, Type> _fp;
- void init(Matrix<4, 4, Type> const & view_matrix_light);
- };
- }
- #endif
- #ifndef CSMTREE_H
- #define CSMTREE_H
- #include <CsmSplit.h>
- #include <boost/pool/object_pool.hpp>
- #include <Primitive.h>
- #include <CsmNodePool.h>
- namespace Log2
- {
- class BoundingVolumeHierarchy;
- class CsmTree
- {
- using BV = typename Primitive::BV;
- using Type = typename Primitive::Type;
- class NodePool;
- public:
- CsmTree(CsmSplit* begin, CsmSplit* end, Matrix<4, 4, Type> const & view_matrix_light);
- ~CsmTree();
- CsmNode* root();
- void descendVisible(BoundingVolumeHierarchy& bvh, CullingParams const & cp, Callback2 const & cb);
- CsmNode* createNode(CsmSplit * begin, CsmSplit * end, Matrix<4, 4, Type> const & view_matrix_light);
- private:
- CsmNode* createInternalNode(CsmSplit* begin, CsmSplit* end, Matrix<4, 4, Type> const & view_matrix_light);
- CsmNode* createLeafNode(CsmSplit* cs);
- CsmNode* _root;
- };
- }
- #endif
- #ifndef DESCENDABLE_H
- #define DESCENDABLE_H
- #include <Callback.h>
- namespace Log2
- {
- class BVHInternalNode;
- class BVHLeafNode;
- class CsmInternalNode;
- class CsmLeafNode;
- class CullingParams;
- class Descendable
- {
- public:
- virtual void descendVisible(Descendable& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendVisible(BVHInternalNode& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendVisible(BVHLeafNode& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendVisible(CsmInternalNode& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendVisible(CsmLeafNode& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendContributing(Descendable& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendContributing(BVHInternalNode& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendContributing(BVHLeafNode& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendContributing(CsmInternalNode& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendContributing(CsmLeafNode& other, CullingParams const & cp, Callback2 const & cb) {};
- virtual void descendAll(Descendable& other, Callback2::CbFunc const & cb) {};
- virtual void descendAll(BVHInternalNode& other, Callback2::CbFunc const & cb) {};
- virtual void descendAll(BVHLeafNode& other, Callback2::CbFunc const & cb) {};
- virtual void descendAll(CsmInternalNode& other, Callback2::CbFunc const & cb) {};
- virtual void descendAll(CsmLeafNode& other, Callback2::CbFunc const & cb) {};
- };
- }
- #endif
- #ifndef EULERROTATION_H
- #define EULERROTATION_H
- #include <math/MathHelpers.h>
- #include <math/Log2Math.h>
- #include <math/MatVecHelpers.h>
- namespace Log2
- {
- template<typename T>
- class EulerRotation
- {
- public:
- EulerRotation() = default;
- EulerRotation(Vector<3, T> const & radians) : _radians(radians)
- {}
- auto rotationX() const
- {
- return rotation3Dx(radians().at<0>());
- }
- auto rotationY() const
- {
- return rotation3Dy(radians().at<1>());
- }
- auto rotation() const
- {
- return rotationY() * rotationX();
- }
- auto right(Matrix<3, 3, T> const & rot) const
- {
- return rot * Vector<3, T>(static_cast<T>(-1), static_cast<T>(0), static_cast<T>(0));
- }
- auto right() const
- {
- return right(rotation());
- }
- auto direction(Matrix<3, 3, T> const & rot) const
- {
- return rot * Vector<3, T>(static_cast<T>(0), static_cast<T>(0), static_cast<T>(1));
- }
- auto direction() const
- {
- return direction(rotation());
- }
- auto up(Vector<3, T> const & right, Vector<3, T> const & direction) const
- {
- return cross(right, direction);
- }
- auto up() const
- {
- return up(rotation());
- }
- auto up(Matrix<3, 3, T> const & rot) const
- {
- return up(right(rot), direction(rot));
- }
- auto viewMatrix(Vector<3, T> const & pos) const
- {
- auto rot = rotation();
- auto r = right(rot);
- auto d = direction(rot);
- return MathHelpers::viewMatrix(pos, r, up(r, d), d);
- }
- auto viewMatrix() const
- {
- auto rot = rotation();
- auto r = right(rot);
- auto d = direction(rot);
- return MathHelpers::viewMatrix(r, up(r, d), d);
- }
- auto viewMatrixInverse(Vector<3, T> const & pos) const
- {
- auto rot = rotation();
- auto r = right(rot);
- auto d = direction(rot);
- return MathHelpers::viewMatrixInverse(pos, r, up(r, d), d);
- }
- auto const & radians() const
- {
- return _radians;
- }
- auto degrees() const
- {
- return Log2::degrees(_radians);
- }
- private:
- Vector<3, T> _radians = static_cast<T>(0);
- };
- }
- #endif // !EULERROTATION_H
- #ifndef FIXEDTIMESTEPSYSTEM_H
- #define FIXEDTIMESTEPSYSTEM_H
- #include <memory>
- #include <System.h>
- namespace Log2
- {
- class Entity;
- class FixedTimestepSystem : public System
- {
- public:
- FixedTimestepSystem() = default;
- virtual ~FixedTimestepSystem() = default;
- virtual bool update() override;
- virtual void updateSystem() = 0;
- private:
- float _acc = 0.f;
- protected:
- float const _dt = 1.f / 60.f;
- };
- }
- #endif
- #ifndef FRUSTUMPLANES_H
- #define FRUSTUMPLANES_H
- #include <math/Log2Math.h>
- #include <array>
- #include <Plane.h>
- namespace Log2
- {
- template<unsigned Dim, typename T>
- class FrustumPlanes
- {
- public:
- FrustumPlanes() = default;
- using Matrix = Matrix<Dim + 1, Dim + 1, T>;
- static FrustumPlanes create(Matrix const & vp)
- {
- FrustumPlanes fp;
- FillPlanes<Dim * 2u - 1u>::call(fp._planes, vp);
- return fp;
- }
- template<unsigned index>
- struct FillPlanes
- {
- static void call(Plane<Dim, T>* planes, Matrix const & vp)
- {
- *(planes + index) = Plane<Dim, T>((vp.row<Dim>() + vp.row<index / 2u>() * static_cast<T>(index % 2 ? -1 : 1)) * static_cast<T>(-1));
- FillPlanes<index - 1u>::call(planes, vp);
- }
- };
- template<>
- struct FillPlanes<0>
- {
- static void call(Plane<3, T>* planes, Matrix const & vp)
- {
- *planes = Plane<3, T>((vp.row<Dim>() + vp.row<0>()) * static_cast<T>(-1));
- }
- };
- FrustumPlanes(FrustumPlanes const & other) = default;
- FrustumPlanes& operator=(FrustumPlanes const & other) = default;
- template<unsigned index>
- auto const & plane() const
- {
- return _planes[index];
- }
- auto const * begin() const
- {
- return _planes;
- }
- auto const * end() const
- {
- return _planes + 6u;
- }
- private:
- Plane<3, T> _planes [Dim * 2u];
- };
- }
- #endif // !FRUSTUMPLANES_H
- #ifndef INTERSECTIONTESTS_H
- #define INTERSECTIONTESTS_H
- #include <AABB.h>
- #include <Sphere.h>
- #include <array>
- #include <Ray.h>
- #include <tuple>
- #include <FrustumPlanes.h>
- namespace Log2
- {
- class Primitive;
- enum class IntersectionResult
- {
- INSIDE, OUTSIDE, INTERSECTING
- };
- class IntersectResult
- {
- public:
- IntersectResult(IntersectionResult const & res) : _res(res)
- {}
- auto intersecting() const
- {
- return _res == IntersectionResult::INTERSECTING;
- }
- auto inside() const
- {
- return _res == IntersectionResult::INSIDE;
- }
- operator bool() const { return _res != IntersectionResult::OUTSIDE; }
- private:
- IntersectionResult _res;
- };
- static bool intersects(IntersectionResult const & ir)
- {
- return ir != IntersectionResult::OUTSIDE;
- }
- struct IntersectedPlanes
- {
- unsigned char _mask;
- IntersectedPlanes() : _mask(0u)
- {}
- IntersectedPlanes(unsigned char const & mask) : _mask(mask)
- {
- }
- template<unsigned index>
- void set()
- {
- _mask |= 1u << index;
- }
- template<unsigned index>
- auto isSet() const
- {
- return (_mask >> index) & 1u;
- }
- auto intersects() const
- {
- return _mask != 0u;
- }
- };
- template<typename Type, typename Matrix>
- class IntersectRayResult
- {
- public:
- IntersectRayResult() = default;
- IntersectRayResult(Type const & z_far) : _nearestT(z_far)
- {}
- auto update(Type const & t, Matrix const * nearest_transform, Primitive* nearest)
- {
- _nearestT = t;
- _nearestTransform = nearest_transform;
- _nearest = nearest;
- }
- auto update(typename Ray<3, Type>::IntersectionResult const & res, Matrix const * nearest_transform, Primitive* nearest)
- {
- _uv = res.uv();
- _nearestT = res.t();
- _nearestTransform = nearest_transform;
- _nearest = nearest;
- }
- operator bool() const { return _nearest != nullptr; }
- auto const & uv() const
- {
- return _uv;
- }
- auto const & nearestT() const
- {
- return _nearestT;
- }
- auto const & nearestTransform() const
- {
- return _nearestTransform;
- }
- auto* nearest()
- {
- return _nearest;
- }
- private:
- Vector<2, Type> _uv;
- Type _nearestT = std::numeric_limits<Type>::max();
- Matrix const * _nearestTransform;
- Primitive* _nearest = nullptr;
- };
- template<typename Type>
- class IntersectRayBVResult
- {
- public:
- IntersectRayBVResult(bool const & intersects, Type const & t) :
- _intersects(intersects),
- _t(t)
- {}
- operator bool const & () const { return _intersects; }
- auto const & t() const
- {
- return _t;
- }
- private:
- bool _intersects;
- Type _t;
- };
- class IntersectionTests
- {
- public:
- IntersectionTests() = delete;
- using IR = IntersectionResult;
- /**
- * It is assumed that the plane normal defines the outside of the plane.
- */
- template<unsigned Dim, typename T>
- static auto intersectPlane(Plane<Dim, T> const & plane, struct AABB<Dim, T>::CenterExtent const & ce)
- {
- auto e = dot(ce._halfExtent, plane.absNormal());
- auto s = plane.distance(ce._center);
- if (s > e) {
- return IR::OUTSIDE;
- }
- return s < -e ? IR::INSIDE : IR::INTERSECTING;
- }
- template<unsigned Dim, typename T>
- static auto intersectPlane(Plane<Dim, T> const & plane, Sphere<Dim, T> const & sphere)
- {
- auto dist = plane.distance(sphere.center());
- if (dist > sphere.radius()) {
- return IR::OUTSIDE;
- }
- return dist < -sphere.radius() ? IR::INSIDE : IR::INTERSECTING;
- }
- template<unsigned Dim, typename T>
- static auto outsidePlane(Plane<Dim, T> const & plane, struct AABB<Dim, T>::CenterExtent const & ce)
- {
- return plane.distance(ce._center) > dot(ce._halfExtent, plane.absNormal());
- }
- template<unsigned Dim, typename T>
- static auto outsidePlane(Plane<Dim, T> const & plane, Sphere<Dim, T> const & s)
- {
- return plane.distance(s.center()) > s.radius();
- }
- template<unsigned Dim, typename T>
- static auto outsideFrustum(AABB<Dim, T> const & aabb, FrustumPlanes<Dim, T> const & fp)
- {
- return FrustumCheck<Dim, T, Dim * 2u - 1u>::outside(aabb.centerExtent(), fp);
- }
- template<unsigned Dim, typename T>
- static auto outsideFrustum(Sphere<Dim, T> const & s, FrustumPlanes<Dim, T> const & fp)
- {
- return FrustumCheck<Dim, T, Dim * 2u - 1u>::outside(s, fp);
- }
- template<unsigned Dim, typename T>
- static auto intersectFrustum(AABB<Dim, T> const & aabb, FrustumPlanes<Dim, T> const & fp)
- {
- bool intersecting = false;
- return IntersectResult(FrustumCheck<Dim, T, Dim * 2u - 1u>::call(aabb.centerExtent(), fp, intersecting));
- }
- template<unsigned Dim, typename T>
- static auto intersectFrustum(AABB<Dim, T> const & aabb, FrustumPlanes<Dim, T> const & fp, IntersectedPlanes const & in, IntersectedPlanes& out)
- {
- return IntersectResult(FrustumCheck<Dim, T, Dim * 2u - 1u>::call(aabb.centerExtent(), fp, in, out));
- }
- template<unsigned Dim, typename T, unsigned index>
- struct FrustumCheck
- {
- static IR call(struct AABB<Dim, T>::CenterExtent const & ce, FrustumPlanes<Dim, T> const & fp, bool& intersecting)
- {
- auto result = intersectPlane(fp.plane<index>(), ce);
- if (result == IR::OUTSIDE) {
- return IR::OUTSIDE;
- }
- intersecting = intersecting || result == IR::INTERSECTING;
- return FrustumCheck<Dim, T, index - 1u>::call(ce, fp, intersecting);
- }
- static IR call(Sphere<Dim, T> const & s, FrustumPlanes<Dim, T> const & fp, bool& intersecting)
- {
- auto result = intersectPlane(fp.plane<index>(), s);
- if (result == IR::OUTSIDE) {
- return IR::OUTSIDE;
- }
- intersecting = intersecting || result == IR::INTERSECTING;
- return FrustumCheck<Dim, T, index - 1u>::call(s, fp, intersecting);
- }
- static IR call(struct AABB<Dim, T>::CenterExtent const & ce, FrustumPlanes<Dim, T> const & fp, IntersectedPlanes const & in, IntersectedPlanes & out)
- {
- if (in.isSet<index>()) {
- auto result = intersectPlane(fp.plane<index>(), ce);
- if (result == IR::OUTSIDE) {
- return IR::OUTSIDE;
- }
- else if (result == IR::INTERSECTING) {
- out.set<index>();
- }
- }
- return FrustumCheck<Dim, T, index - 1u>::call(ce, fp, in, out);
- }
- static bool outside(struct AABB<Dim, T>::CenterExtent const & ce, FrustumPlanes<Dim, T> const & fp)
- {
- return outsidePlane(fp.plane<index>(), ce) || FrustumCheck<Dim, T, index - 1u>::outside(ce, fp);
- }
- static bool outside(Sphere<Dim, T> const & s, FrustumPlanes<Dim, T> const & fp)
- {
- return outsidePlane(fp.plane<index>(), s) || FrustumCheck<Dim, T, index - 1u>::outside(s, fp);
- }
- };
- template<unsigned Dim, typename T>
- struct FrustumCheck<Dim, T, 0>
- {
- static IR call(struct AABB<Dim, T>::CenterExtent const & ce, FrustumPlanes<Dim, T> const & fp, bool& intersecting)
- {
- auto result = intersectPlane(fp.plane<0>(), ce);
- if (result == IR::OUTSIDE) {
- return IR::OUTSIDE;
- }
- return intersecting || result == IR::INTERSECTING ? IR::INTERSECTING : IR::INSIDE;
- }
- static IR call(Sphere<Dim, T> const & s, FrustumPlanes<Dim, T> const & fp, bool& intersecting)
- {
- auto result = intersectPlane(fp.plane<0>(), s);
- if (result == IR::OUTSIDE) {
- return IR::OUTSIDE;
- }
- return intersecting || result == IR::INTERSECTING ? IR::INTERSECTING : IR::INSIDE;
- }
- static IR call(struct AABB<Dim, T>::CenterExtent const & ce, FrustumPlanes<Dim, T> const & fp, IntersectedPlanes const & in, IntersectedPlanes & out)
- {
- if (in.isSet<0>()) {
- auto result = intersectPlane(fp.plane<0>(), ce);
- if (result == IR::OUTSIDE) {
- return IR::OUTSIDE;
- }
- else if (result == IR::INTERSECTING) {
- out.set<0>();
- }
- }
- return out.intersects() ? IR::INTERSECTING : IR::INSIDE;
- }
- static bool outside(struct AABB<Dim, T>::CenterExtent const & ce, FrustumPlanes<Dim, T> const & fp)
- {
- return outsidePlane(fp.plane<0>(), ce);
- }
- static bool outside(Sphere<Dim, T> const & s, FrustumPlanes<Dim, T> const & fp)
- {
- return outsidePlane(fp.plane<0>(), s);
- }
- };
- template<unsigned Dim, typename T>
- static auto intersectFrustum(Sphere<Dim, T> const & sphere, FrustumPlanes<Dim, T> const & fp)
- {
- bool intersecting = false;
- return FrustumCheck<Dim, T, Dim * 2u - 1u>::call(sphere, fp, intersecting);
- }
- template<unsigned Dim, typename T>
- static IntersectRayBVResult<T> intersectRay(AABB<Dim, T> const & aabb, Ray<Dim, T> const & ray)
- {
- auto t1 = (aabb.min() - ray.origin()) * ray.invDir();
- auto t2 = (aabb.max() - ray.origin()) * ray.invDir();
- auto t_min = maxReduce(minimum(t1, t2));
- auto t_max = minReduce(maximum(t1, t2));
- return { t_min <= t_max && t_max >= static_cast<T>(0), t_min };
- }
- template<unsigned Dim, typename T>
- static auto continueSearch(AABB<Dim, T> const & aabb, Ray<Dim, T> const & ray, T const & nearest_dist)
- {
- auto result = intersectRay(aabb, ray);
- return result && result.t() < nearest_dist;
- }
- template<typename T, unsigned Dim, typename Matrix>
- static auto continueSearch(AABB<Dim, T> const & aabb, Ray<Dim, T> const & ray, IntersectRayResult<T, Matrix> const & res)
- {
- return continueSearch(aabb, ray, res.nearestT());
- }
- template<typename T, unsigned Dim, typename Matrix>
- static auto continueSearch(AABB<Dim, T> const & aabb_local, Ray<Dim, T> const & ray_local, Ray<Dim, T> const & ray_world,
- Matrix const & mat, T const & nearest_dist)
- {
- auto result = intersectRay(aabb_local, ray_local);
- return result && distance(ray_world.origin(), MathHelpers::transformPoint(mat, ray_local.pos(result.t()))) < nearest_dist;
- }
- template<typename T, unsigned Dim, typename Matrix>
- static auto continueSearch(AABB<Dim, T> const & aabb_local, Ray<Dim, T> const & ray_local, Ray<Dim, T> const & ray_world,
- Matrix const & mat, IntersectRayResult<T, Matrix> const & res)
- {
- return continueSearch(aabb_local, ray_local, ray_world, mat, res.nearestT());
- }
- };
- }
- #endif // !INTERSECTIONTESTS_H
- #ifndef LIGHT_H
- #define LIGHT_H
- #include "math/Log2Math.h"
- #include "Mesh.h"
- #include <memory>
- #include <StackTrivial.h>
- #include <EulerRotation.h>
- #include <CsmSplit.h>
- namespace Log2
- {
- class Light
- {
- public:
- Light(Vec3f const & color);
- Vec3f const & intensity() const;
- void setIntensity(Vec3f const & i);
- protected:
- Vec3f _intensity = Vec3f(1.f);
- };
- class DirectionalLight : public Light
- {
- public:
- DirectionalLight(Vec3f const & color, Vec3f const & euler_radians);
- float _ambientPower = 0.3f;
- template<typename T>
- auto csmSplits(T const & aspect_ratio, T const & near_plane, T const & fov_degrees, Matrix<4, 4, T> const & view_matrix_inverse,
- T const & shadow_map_size, StackTrivial<T> const & frustum_splits, CsmSplit* splits, Matrix<4, 4, T>* vp)
- {
- auto view_matrix_light = viewMatrix();
- for (auto ptr = frustum_splits.begin(); ptr != frustum_splits.end(); ptr++) {
- auto vp_inverse = view_matrix_inverse * inverse(MathHelpers::projectionMatrixPerspective<T>(fov_degrees, aspect_ratio, ptr == frustum_splits.begin() ? near_plane : *(ptr - 1), *ptr));
- auto cube_ndc = MathHelpers::cubeNDC<T>();
- AABB<3, T> aabb_light(AABB<3, T>::fromTransform<cube_ndc.size()>(cube_ndc.data(), view_matrix_light * vp_inverse));
- auto units_per_texel = (aabb_light.max() - aabb_light.min()) / shadow_map_size;
- aabb_light.min() = floor(aabb_light.min() / units_per_texel) * units_per_texel;
- aabb_light.max() = floor(aabb_light.max() / units_per_texel) * units_per_texel;
- AABB<3, T> aabb_light_cull = aabb_light;
- aabb_light_cull.min().at<2>() -= _maxShadowCastDistance;
- (splits++)->set(aabb_light_cull, aabb_light, view_matrix_light, vp++);
- }
- }
- Mat4f viewMatrix() const;
- Vec3f direction() const;
- Vec3f const & eulerRadians() const;
- Vec3f eulerDegrees() const;
- void setEulerRadians(Vec3f const & euler_radians);
- void setEulerDegrees(Vec3f const & euler_degrees);
- void setMaxShadowCastDistance(float const & distance);
- float const & getMaxShadowCastDistance() const;
- private:
- EulerRotation<float> _er;
- float _maxShadowCastDistance = 1000.f;
- };
- }
- #endif
- #ifndef MESH_H
- #define MESH_H
- #include <vector>
- #include <array>
- #include <memory>
- #include <functional>
- #include <Vertex.h>
- #include <AABB.h>
- #include <Sphere.h>
- #include <BoundingVolumeHierarchy.h>
- #include <Triangle.h>
- #include <StackTrivial.h>
- #include <boost/pool/object_pool.hpp>
- namespace Log2
- {
- class Material;
- class Mesh
- {
- public:
- using Type = Primitive::Type;
- Mesh() = default;
- Mesh(StackTrivial<Vertex>&& vertices, StackTrivial<unsigned int>&& indices, std::shared_ptr<Material> const * materials, unsigned int material_index);
- StackTrivial<Vertex> const & vertices() const;
- StackTrivial<unsigned int> const & indices() const;
- void setVertices(StackTrivial<Vertex>&& vertices);
- void setIndices(StackTrivial<unsigned>&& indices);
- unsigned const & materialIndex() const;
- AABB3f const & aabb() const;
- Sphere3f const & sphere() const;
- void setMaterialIndex(unsigned const & material_index);
- void setMaterial(std::shared_ptr<Material> const & material);
- std::shared_ptr<Material> const & material() const;
- struct Proxy;
- using Ray = typename BoundingVolumeHierarchy::Ray;
- BoundingVolumeHierarchy * bvh();
- void triangles(Vertex* vertices, boost::object_pool<Triangle>& tri_pool, StackTrivial<Primitive*>& triangles) const;
- std::shared_ptr<BoundingVolumeHierarchy> getTransformedBVH(Matrix<4, 4, Type> const & transform,
- Matrix<3, 3, Type> const & m_inv_transpose, boost::object_pool<Triangle>& tri_pool, StackTrivial<Vertex>& vertices) const;
- void calculateTangentSpace();
- private:
- StackTrivial<Vertex> _vertices;
- StackTrivial<unsigned int> _indices;
- boost::object_pool<Triangle> _trianglePool;
- unsigned int _materialIndex;
- std::shared_ptr<Material> _material;
- AABB3f _aabb;
- Sphere3f _sphere;
- std::unique_ptr<BoundingVolumeHierarchy> _bvh;
- void init();
- };
- }
- #endif
- #ifndef PLANE_H
- #define PLANE_H
- #include <math/Log2Math.h>
- namespace Log2
- {
- template<unsigned Dim, typename T>
- class Plane
- {
- public:
- Plane() = default;
- Plane(Vector<Dim, T> const & normal, T const & bias) :
- _normal(normal),
- _bias(bias)
- {
- normalize();
- }
- explicit Plane(Vector<Dim + 1, T> const & normal_bias) :
- _normal(normal_bias.reduce<Dim>()),
- _bias(normal_bias[Dim])
- {
- normalize();
- }
- auto normalize()
- {
- auto inv_len = static_cast<T>(1) / _normal.length();
- _normal *= inv_len;
- _bias *= inv_len;
- }
- auto const & normal() const
- {
- return _normal;
- }
- auto const & bias() const
- {
- return _bias;
- }
- auto normalBias() const
- {
- return Vector<Dim + 1, T>(_normal, _bias);
- }
- auto distance(Vector<Dim, T> const & point) const
- {
- return dot(point, _normal) + _bias;
- }
- auto absNormal() const
- {
- return abs(_normal);
- }
- private:
- Vector<Dim, T> _normal;
- T _bias;
- };
- using Plane2f = Plane<2, float>;
- using Plane3f = Plane<3, float>;
- using Plane2d = Plane<2, double>;
- using Plane3d = Plane<3, double>;
- }
- #endif
- #ifndef TRIANGLE_H
- #define TRIANGLE_H
- #include <Primitive.h>
- #include <vector>
- #include <Vertex.h>
- namespace Log2
- {
- class Particle;
- class Triangle : public Primitive
- {
- public:
- Triangle() = default;
- Triangle(Vec3u const & indices, Vertex* vertices) :
- _indices(indices),
- _vertices(vertices)
- {
- }
- Triangle& operator=(Triangle const & other) = default;
- template<unsigned index>
- auto vertex() const
- {
- static_assert(index <= 2, "Invalid index");
- return _vertices[_indices[index]].position();
- }
- template<unsigned index>
- auto normal() const
- {
- static_assert(index <= 2, "Invalid index");
- return _vertices[_indices[index]].normal();
- }
- auto center() const
- {
- return interpolatePos(static_cast<Type>(1.0 / 3.0));
- }
- auto centerNormal() const
- {
- return interpolateNormal(static_cast<Type>(1.0 / 3.0));
- }
- Vector<3, Type> interpolatePos(Vector<2, Type> const & uv) const
- {
- return interpolateBary(uv, vertex<0>(), vertex<1>(), vertex<2>());
- }
- virtual Vector<3, Type> interpolateNormal(Vector<2, Type> const & uv) const override
- {
- return interpolateBary(uv, normal<0>(), normal<1>(), normal<2>());
- }
- virtual Vector<2, Type> barycentric(Vector<3, Type> const & p)
- {
- return barycentric(vertex<0>(), vertex<1>(), vertex<2>(), p);
- }
- template<unsigned Dim>
- static auto barycentric(Vector<Dim, Type> const & p0, Vector<Dim, Type> const & p1, Vector<Dim, Type> const & p2, Vector<Dim, Type> const & p)
- {
- auto e0 = p1 - p0;
- auto e1 = p2 - p0;
- auto one_over_a = static_cast<Type>(1) / triAreaTimesTwo(e0, e1);
- return Vector<2, Type>(triAreaTimesTwo(p - p0, e1), triAreaTimesTwo(e0, p - p1)) * one_over_a;
- }
- std::array<Vec3f, 3u> getVertices() const
- {
- return { vertex<0>(), vertex<1>(), vertex<2>() };
- }
- virtual BV bv() const override;
- virtual Type squaredSize() const override;
- Ray::IntersectionResult intersectRay(Ray const & ray, Vector<3, Type> const & p0, Vector<3, Type> const & p1, Vector<3, Type> const & p2);
- virtual Ray::IntersectionResult intersectRay(Ray const & ray_local, Ray const & ray_world, Matrix const & mat) override;
- virtual Ray::IntersectionResult intersectRay(Ray const & ray) override;
- virtual Ray::IntersectionResult intersectRay(Ray const & ray, Matrix const & matrix) override;
- virtual void debugTriangle(Vector<4, Type>* _debugTriangle, Matrix const & transform) const override;
- virtual Triangle* toTriangle() override;
- private:
- Vec3u _indices;
- Vertex* _vertices;
- };
- }
- #endif
- #ifndef VERTEX_H
- #define VERTEX_H
- #include <math/Log2Math.h>
- namespace Log2
- {
- struct CompressedNormal
- {
- int _x : 10;
- int _y : 10;
- int _z : 10;
- int _w : 2;
- CompressedNormal() = default;
- explicit CompressedNormal(Vec3f const & normal)
- {
- Vec3i compressed(normal.normalize() * 511.f);
- _x = compressed.at<0>();
- _y = compressed.at<1>();
- _z = compressed.at<2>();
- _w = 1;
- }
- explicit CompressedNormal(Vec3f const & tangent, int const & handedness)
- {
- Vec3i compressed(tangent.normalize() * 511.f);
- _x = compressed.at<0>();
- _y = compressed.at<1>();
- _z = compressed.at<2>();
- _w = handedness;
- }
- auto uncompress() const
- {
- return Vec3f(Vec3i(_x, _y, _z)) / 511.f;
- }
- auto const & w() const
- {
- return _w;
- }
- };
- class Vertex
- {
- public:
- Vertex() = default;
- Vertex(Vec3f const & position) :
- _position(position)
- {
- }
- Vertex(Vec3f const & position, CompressedNormal const & normal) :
- _position(position),
- _normal(normal)
- {
- }
- Vertex(Vec3f const & position, Vec2f const & uv) :
- _position(position),
- _uv(uv)
- {
- }
- Vertex(Vec3f const & position, CompressedNormal const & normal, Vec2f const & uv) :
- _position(position),
- _normal(normal),
- _uv(uv)
- {
- }
- Vertex(Vec3f const & position, CompressedNormal const & normal, Vec2f const & uv, CompressedNormal const & tangent) :
- _position(position),
- _normal(normal),
- _uv(uv),
- _tangent(tangent)
- {
- }
- auto const & position() const
- {
- return _position;
- }
- auto normal() const
- {
- return _normal.uncompress();
- }
- auto const & uv() const
- {
- return _uv;
- }
- auto tangent() const
- {
- return _tangent.uncompress();
- }
- auto bitangent() const
- {
- return cross(normal(), tangent()) * static_cast<float>(_tangent.w());
- }
- auto setPosition(Vec3f const & position)
- {
- _position = position;
- }
- auto setNormal(CompressedNormal const & normal)
- {
- _normal = normal;
- }
- auto setNormal(Vec3f const & normal)
- {
- _normal = CompressedNormal(normal);
- }
- auto setUV(Vec2f const & uv)
- {
- _uv = uv;
- }
- auto setTangent(CompressedNormal const & tangent)
- {
- _tangent = tangent;
- }
- auto setTangent(Vec3f const & tangent)
- {
- _tangent = CompressedNormal(tangent);
- }
- auto set(Vec3f const & t, int const & handedness, Vec3f const & n)
- {
- setTangent(CompressedNormal(t, handedness));
- setNormal(n);
- }
- static size_t positionMemOffset()
- {
- return offsetof(Vertex, _position);
- }
- static size_t normalMemOffset()
- {
- return offsetof(Vertex, _normal);
- }
- static size_t uvMemOffset()
- {
- return offsetof(Vertex, _uv);
- }
- static size_t tangentMemOffset()
- {
- return offsetof(Vertex, _tangent);
- }
- private:
- Vec3f _position;
- CompressedNormal _normal = CompressedNormal(0.f);
- Vec2f _uv;
- CompressedNormal _tangent = CompressedNormal(0.f);
- };
- class VertexUncompressed
- {
- public:
- auto addTangent(Vec3f const & t)
- {
- _t = normalize(_t + t);
- }
- auto addBitangent(Vec3f const & b)
- {
- _b = normalize(_b + b);
- }
- auto addNormal(Vec3f const & n)
- {
- _n = normalize(_n + n);
- }
- auto add(Vec3f const & t, Vec3f const & b, Vec3f const & n)
- {
- addTangent(t);
- addBitangent(b);
- addNormal(n);
- }
- auto const & tangent() const
- {
- return _t;
- }
- auto const & bitangent() const
- {
- return _b;
- }
- auto const & normal() const
- {
- return _n;
- }
- auto const & t() const
- {
- return tangent();
- }
- auto const & b() const
- {
- return bitangent();
- }
- auto const & n() const
- {
- return normal();
- }
- private:
- Vec3f _t = 0.f;
- Vec3f _b = 0.f;
- Vec3f _n = 0.f;
- };
- }
- #endif
- #ifndef PHYSICSCAMERACONTROLLER_H
- #define PHYSICSCAMERACONTROLLER_H
- #include <memory>
- #include <math/Log2Math.h>
- #include <FixedTimestepSystem.h>
- #include <Primitive.h>
- namespace Log2
- {
- class Camera;
- class BoundingVolumeHierarchy;
- class PhysicsCameraController : public FixedTimestepSystem
- {
- private:
- using Type = Primitive::Type;
- using Vector = Vector<3, Type>;
- public:
- PhysicsCameraController(Camera* const & camera, BoundingVolumeHierarchy*& bvh);
- virtual ~PhysicsCameraController() = default;
- virtual void updateSystem() override;
- virtual unsigned getID() override;
- virtual const char* getName() override;
- void setAcceleration(Vector const & dir, Type const & amount);
- void setAngularAcceleration(Vector const & aa);
- Camera * const & getCamera() const;
- void setCamera(Camera * const & camera);
- void setDamping(Type const & damping);
- Vector const & gravity() const;
- void setGravity(Vector const & gravity);
- bool const & collisions() const;
- void setCollisions(bool const & collisions);
- private:
- Camera* _c;
- Vector _acceleration = static_cast<Type>(0);
- Vector _velocity = static_cast<Type>(0);
- Type _damp = DAMP_DEFAULT;
- Vector _angularAcceleration = static_cast<Type>(0);
- Vector _angularVelocity = static_cast<Type>(0);
- Vector _gravity = static_cast<Type>(0);
- BoundingVolumeHierarchy*& _bvh;
- bool _collisions = true;
- static constexpr const Type DAMP_DEFAULT = static_cast<Type>(0.95);
- static constexpr const Type DAMP_INTERIOR = static_cast<Type>(0.7);
- };
- }
- #endif
- #ifndef MATHHELPERS_H
- #define MATHHELPERS_H
- #include <math/Log2Math.h>
- #define GLM_ENABLE_EXPERIMENTAL
- #include <glm/gtc/matrix_transform.hpp>
- #include <array>
- namespace Log2
- {
- template<unsigned Dim, typename T>
- class AABB;
- class MathHelpers
- {
- public:
- template<typename T>
- static auto cubeNDC()
- {
- std::array<Vector<3, T>, 8> ret;
- FillCubeNDC<T>::call(ret.data());
- return ret;
- }
- template<typename T, unsigned i = 7>
- struct FillCubeNDC
- {
- static void call(Vector<3, T>* res)
- {
- *(res + i) = Vector<3, T>(i & 4 ? -static_cast<T>(1) : static_cast<T>(1), i & 2 ? -static_cast<T>(1) : static_cast<T>(1), i & 1 ? -static_cast<T>(1) : static_cast<T>(1));
- FillCubeNDC<T, i - 1u>::call(res);
- }
- };
- template<typename T>
- struct FillCubeNDC<T, 0>
- {
- static void call(Vector<3, T>* res)
- {
- *res = Vector<3, T>(0 & 4 ? -static_cast<T>(1) : static_cast<T>(1), 0 & 2 ? -static_cast<T>(1) : static_cast<T>(1), 0 & 1 ? -static_cast<T>(1) : static_cast<T>(1));
- }
- };
- template<typename T>
- static auto projectionMatrixPerspective(T const & fov_degrees, T const & aspect_ratio, T const & z_near, T const & z_far)
- {
- using Vec = Vector<4, T>;
- auto const t = tan(radians(fov_degrees) * static_cast<T>(0.5));
- auto const sx = static_cast<T>(1) / (aspect_ratio * t);
- auto const sy = static_cast<T>(1) / t;
- auto const sz = static_cast<T>(1) / (z_far - z_near);
- return Matrix<4, 4, T>({ Vec(sx, static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)),
- Vec(static_cast<T>(0), sy, static_cast<T>(0), static_cast<T>(0)),
- Vec(static_cast<T>(0), static_cast<T>(0), (z_far + z_near) * sz, static_cast<T>(1)),
- Vec(static_cast<T>(0), static_cast<T>(0), -(static_cast<T>(2) * z_far * z_near) * sz, static_cast<T>(0)) });
- }
- template<typename T>
- static auto projectionMatrixOrtho(AABB<3, T> const & aabb)
- {
- auto const c = aabb.centerTimesTwo() * static_cast<T>(-1);
- auto const e = Vector<3, T>(static_cast<T>(1)) / aabb.extent();
- return Matrix<4, 4, T>({ Vector<4, T>(static_cast<T>(2) * e.at<0>(), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)),
- Vector<4, T>(static_cast<T>(0), static_cast<T>(2) * e.at<1>(), static_cast<T>(0), static_cast<T>(0)),
- Vector<4, T>(static_cast<T>(0), static_cast<T>(0), static_cast<T>(2) * e.at<2>(), static_cast<T>(0)),
- Vector<4, T>(c * e, static_cast<T>(1)) });
- }
- template<typename T>
- static auto viewMatrix(Vector<3, T> const & pos, Vector<3, T> const & right, Vector<3, T> const & up, Vector<3, T> const & direction)
- {
- return Matrix<4, 4, T>({ Vector<4, T>(right.at<0>(), up.at<0>(), direction.at<0>(), static_cast<T>(0)),
- Vector<4, T>(right.at<1>(), up.at<1>(), direction.at<1>(), static_cast<T>(0)),
- Vector<4, T>(right.at<2>(), up.at<2>(), direction.at<2>(), static_cast<T>(0)),
- Vector<4, T>(-dot(right, pos), -dot(up, pos), -dot(direction, pos), static_cast<T>(1)) });
- }
- template<typename T>
- static auto viewMatrixInverse(Vector<3, T> const & pos, Vector<3, T> const & right, Vector<3, T> const & up, Vector<3, T> const & direction)
- {
- return Matrix<4, 4, T>({ Vector<4, T>(right, static_cast<T>(0)),
- Vector<4, T>(up, static_cast<T>(0)),
- Vector<4, T>(direction, static_cast<T>(0)),
- Vector<4, T>(pos, static_cast<T>(1)) });
- }
- template<typename T>
- static auto viewMatrix(Vector<3, T> const & right, Vector<3, T> const & up, Vector<3, T> const & direction)
- {
- return Matrix<4, 4, T>({ Vector<4, T>(right.at<0>(), up.at<0>(), direction.at<0>(), static_cast<T>(0)),
- Vector<4, T>(right.at<1>(), up.at<1>(), direction.at<1>(), static_cast<T>(0)),
- Vector<4, T>(right.at<2>(), up.at<2>(), direction.at<2>(), static_cast<T>(0)),
- Vector<4, T>(static_cast<T>(0), static_cast<T>(0), static_cast<T>(0), static_cast<T>(1)) });
- }
- template<typename T>
- static auto hash(Vector<2, T> const & p, Vector<3, T> const & seed = Vector<3, T>(static_cast<T>(24.33), static_cast<T>(52.23), static_cast<T>(14721.28)))
- {
- return fract(std::sin(dot(p, seed.xy())) * seed.z());
- }
- template<typename T>
- static auto valueNoise(Vector<2, T> const & p, Vector<3, T> const & seed = Vector<3, T>(static_cast<T>(24.33), static_cast<T>(52.23), static_cast<T>(14721.28)))
- {
- auto start = floor(p);
- auto end = start + static_cast<T>(1);
- auto weights = smoothstep(start, end, p);
- return lerp(lerp(hash(start, seed), hash(Vector<2, T>(end.x(), start.y()), seed), weights.x()), lerp(hash(Vector<2, T>(start.x(), end.y()), seed), hash(end, seed), weights.x()), weights.y());
- }
- template<typename T>
- static auto hash(T const & p)
- {
- return fract(std::sin(p) * static_cast<T>(14721.28));
- }
- template<typename T>
- static auto valueNoise(T const & p)
- {
- auto start = std::floor(p);
- auto end = start + static_cast<T>(1);
- return lerp(hash(start), hash(end), smoothstep(start, end, p));
- }
- template<typename T>
- static auto fract(T val)
- {
- return val - std::floor(val);
- }
- template<typename T>
- static auto elementsPerThread(T const & num_elements, T const & num_threads)
- {
- return static_cast<T>(std::ceil(static_cast<float>(num_elements) / static_cast<float>(num_threads)));
- }
- template <typename T, unsigned index>
- struct ComputePow
- {
- static auto call(const T& base)
- {
- return base * ComputePow<T, index - 1>::call(base);
- }
- };
- template <typename T>
- struct ComputePow<T, 0>
- {
- static auto call(const T& base)
- {
- return base;
- }
- };
- template <unsigned exponent, typename T>
- static auto pow(T const & base)
- {
- return exponent ? ComputePow<T, exponent - 1>::call(base) : static_cast<T>(1);
- }
- template<unsigned Dim, typename T>
- static auto transformVector(Matrix<Dim + 1, Dim + 1, T> const & mat, Vector<Dim, T> const & vec)
- {
- return transform<Dim, T, 0>(mat, vec);
- }
- template<unsigned Dim, typename T>
- static auto transformPoint(Matrix<Dim + 1, Dim + 1, T> const & mat, Vector<Dim, T> const & point)
- {
- return transform<Dim, T, 1>(mat, point);
- }
- template<unsigned Dim, typename T, unsigned Hom>
- static auto transform(Matrix<Dim + 1, Dim + 1, T> const & mat, Vector<Dim, T> const & v)
- {
- return (mat * Vector<Dim + 1, T>(v, static_cast<T>(Hom))).reduce<Dim>();
- }
- template<unsigned Dim, typename T>
- static auto transformReduce(Matrix<Dim + 1, Dim + 1, T> const & mat, Vector<Dim, T> const & v)
- {
- return Matrix<Dim, Dim, T>(mat) * v;
- }
- };
- }
- #endif
- #include <BVHInternalNode.h>
- #include <CullingParams.h>
- #include <BVHNodePool.h>
- #include <StackTrivial.h>
- #include <BVHLeafNode.h>
- #include <CsmInternalNode.h>
- #include <CsmLeafNode.h>
- namespace Log2
- {
- void BVHInternalNode::init(PrimitiveInfo const * begin, PrimitiveInfo const * const end)
- {
- while (begin != end) {
- insert(*begin++);
- }
- }
- bool BVHInternalNode::contributes(CullingParams const & cp) const
- {
- return _bv.contributes(cp.camPos(), cp.thresh(), _maxSquaredSize);
- }
- bool BVHInternalNode::fullyContributes(CullingParams const & cp) const
- {
- return _bv.fullyContributes(cp.camPos(), cp.thresh(), _minSquaredSize);
- }
- IntersectResult BVHInternalNode::intersectFrustum(CullingParams const & cp) const
- {
- return IntersectionTests::intersectFrustum(_bv, cp.frustumPlanes());
- }
- IntersectResult BVHInternalNode::intersectFrustum(CullingParams const & cp, IntersectedPlanes const & in, IntersectedPlanes& out) const
- {
- return IntersectionTests::intersectFrustum(_bv, cp.frustumPlanes(), in, out);
- }
- ContribResult BVHInternalNode::computeContribution(CullingParams const & cp) const
- {
- return _bv.computeContribution(cp.camPos(), cp.thresh(), _minSquaredSize, _maxSquaredSize);
- }
- BVHInternalNode::BVHInternalNode(PrimitiveInfo* const begin, PrimitiveInfo* const end, BVHNodePool& np)
- : BVHNode(),
- _bv(begin->bv()),
- _minSquaredSize(begin->squaredSize()),
- _maxSquaredSize(begin->squaredSize())
- {
- init(begin + 1u, end);
- auto const axis = _bv.longestAxis();
- auto const bv_center = _bv.center(axis);
- auto* const mid = Algorithm::partitionForceSplit(begin, end, [&axis, &bv_center](PrimitiveInfo const & p) {
- return p.bv().center(axis) < bv_center;
- });
- _left = np.createNode(begin, mid);
- _right = np.createNode(mid, end);
- }
- void BVHInternalNode::recurseVisible(CullingParams const & cp, Callback const & cb) const
- {
- _left->cullVisiblePrimitives(cp, cb);
- _right->cullVisiblePrimitives(cp, cb);
- }
- void BVHInternalNode::recurseVisible(CullingParams const & cp, IntersectedPlanes const & ip, Callback const & cb) const
- {
- _left->cullVisiblePrimitives(cp, ip, cb);
- _right->cullVisiblePrimitives(cp, ip, cb);
- }
- void BVHInternalNode::recurseContributing(CullingParams const & cp, Callback const & cb) const
- {
- _left->cullContributingPrimitives(cp, cb);
- _right->cullContributingPrimitives(cp, cb);
- }
- void BVHInternalNode::recurseAll(Callback::CbFunc const & on_render) const
- {
- _left->cullAllPrimitives(on_render);
- _right->cullAllPrimitives(on_render);
- }
- void BVHInternalNode::cullVisiblePrimitives(CullingParams const & cp, Callback const & cb) const
- {
- if (contributes(cp)) {
- if (auto const result = intersectFrustum(cp)) {
- result.intersecting() ? recurseVisible(cp, cb) : recurseContributing(cp, cb);
- }
- }
- }
- void BVHInternalNode::cullVisiblePrimitives(CullingParams const & cp, IntersectedPlanes const & in, Callback const & cb) const
- {
- if (contributes(cp)) {
- IntersectedPlanes out;
- if (auto const result = intersectFrustum(cp, in, out)) {
- result.intersecting() ? recurseVisible(cp, out, cb) : recurseContributing(cp, cb);
- }
- }
- }
- void BVHInternalNode::cullContributingPrimitives(CullingParams const & cp, Callback const & cb) const
- {
- if (auto const result = computeContribution(cp)) {
- result.intersecting() ? recurseContributing(cp, cb) : recurseAll(cb.onRender());
- }
- }
- void BVHInternalNode::cullAllPrimitives(Callback::CbFunc const & on_render) const
- {
- recurseAll(on_render);
- }
- size_t BVHInternalNode::sizeInBytes() const
- {
- return sizeof *this + _left->sizeInBytes() + _right->sizeInBytes();
- }
- void BVHInternalNode::intersectNested(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, std::function<void(Primitive const *)> const & intersect_nested) const
- {
- Type t_first;
- if (_bv.intersects(bv, v, v_inv, t_first) && t_first < min_t_first) {
- _left->intersectNested(bv, v, v_inv, min_t_first, intersect_nested);
- _right->intersectNested(bv, v, v_inv, min_t_first, intersect_nested);
- }
- }
- void BVHInternalNode::intersectPrimitives(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, Primitive const *& nearest) const
- {
- Type t_first;
- if (_bv.intersects(bv, v, v_inv, t_first) && t_first < min_t_first) {
- _left->intersectPrimitives(bv, v, v_inv, min_t_first, nearest);
- _right->intersectPrimitives(bv, v, v_inv, min_t_first, nearest);
- }
- }
- void BVHInternalNode::countNodes(unsigned& internal_nodes, unsigned& leaf_nodes) const
- {
- _left->countNodes(++internal_nodes, leaf_nodes);
- _right->countNodes(internal_nodes, leaf_nodes);
- }
- void BVHInternalNode::recurseNearest(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive const *& nearest, Type& nearest_t, Matrix const *& nearest_transform) const
- {
- _left->findNearest(ray_local, ray_world, transform, nearest, nearest_t, nearest_transform);
- _right->findNearest(ray_local, ray_world, transform, nearest, nearest_t, nearest_transform);
- }
- void BVHInternalNode::recurseNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res)
- {
- _left->findNearestPrecise(ray_local, ray_world, transform, res);
- _right->findNearestPrecise(ray_local, ray_world, transform, res);
- }
- void BVHInternalNode::findNearest(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive const *& nearest, Type& nearest_t, Matrix const *& nearest_transform) const
- {
- if (IntersectionTests::continueSearch(_bv, ray_local, ray_world, *transform, nearest_t)) {
- recurseNearest(ray_local, ray_world, transform, nearest, nearest_t, nearest_transform);
- }
- }
- void BVHInternalNode::findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res)
- {
- if (IntersectionTests::continueSearch(_bv, ray_local, ray_world, *transform, res)) {
- recurseNearestPrecise(ray_local, ray_world, transform, res);
- }
- }
- void BVHInternalNode::findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive* parent, IntersectRayResult& res, Primitive*& parent_res)
- {
- if (IntersectionTests::continueSearch(_bv, ray_local, ray_world, *transform, res)) {
- _left->findNearestPrecise(ray_local, ray_world, transform, parent, res, parent_res);
- _right->findNearestPrecise(ray_local, ray_world, transform, parent, res, parent_res);
- }
- }
- void BVHInternalNode::findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res, StackTrivial<NodePtr>& stack)
- {
- if (IntersectionTests::continueSearch(_bv, ray_local, ray_world, *transform, res)) {
- stack.push_back(_right);
- stack.push_back(_left);
- }
- }
- void BVHInternalNode::findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested)
- {
- if (IntersectionTests::continueSearch(_bv, ray, res)) {
- NodePtr nodes[2] = { _left, _right };
- if (_right->dist(ray) < _left->dist(ray)) {
- Algorithm::swap(*nodes, *(nodes + 1u));
- }
- (*nodes)->findNearestNested(ray, res, find_nested);
- (*(nodes + 1u))->findNearestNested(ray, res, find_nested);
- }
- }
- void BVHInternalNode::findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested, StackTrivial<NodePtr>& stack)
- {
- if (IntersectionTests::continueSearch(_bv, ray, res)) {
- stack.push_back(_right);
- stack.push_back(_left);
- if (_right->dist(ray) < _left->dist(ray)) {
- Algorithm::swap(stack.back(), *(&stack.back() - 1u));
- }
- }
- }
- bool BVHInternalNode::largerThan(BVHInternalNode const & other) const
- {
- return _bv.largerThan(other._bv);
- }
- void BVHInternalNode::recurseQueryRange(BV const & bv, Callback::CbFunc const & cb) const
- {
- _left->queryRange(bv, cb);
- _right->queryRange(bv, cb);
- }
- void BVHInternalNode::recurseQueryRange(BV const & bv, CullingParams const & cp, Callback::CbFunc const & cb) const
- {
- _left->queryRange(bv, cp, cb);
- _right->queryRange(bv, cp, cb);
- }
- void BVHInternalNode::recurseQueryContributing(CullingParams const & cp, Callback::CbFunc const & cb) const
- {
- _left->queryContributing(cp, cb);
- _right->queryContributing(cp, cb);
- }
- void BVHInternalNode::recurseQueryAll(Callback::CbFunc const & cb) const
- {
- _left->queryAll(cb);
- _right->queryAll(cb);
- }
- void BVHInternalNode::queryRange(BV const & bv, Callback::CbFunc const & cb) const
- {
- if (bv.contains(_bv)) {
- recurseQueryAll(cb);
- }
- else if (bv.intersects(_bv)) {
- recurseQueryRange(bv, cb);
- }
- }
- void BVHInternalNode::queryRange(BV const & bv, CullingParams const & cp, Callback::CbFunc const & cb) const
- {
- if (contributes(cp)) {
- if (bv.contains(_bv)) {
- recurseQueryContributing(cp, cb);
- }
- else if (bv.intersects(_bv)) {
- recurseQueryRange(bv, cp, cb);
- }
- }
- }
- void BVHInternalNode::queryContributing(CullingParams const & cp, Callback::CbFunc const & cb) const
- {
- if (auto const result = computeContribution(cp)) {
- result.intersecting() ? recurseQueryContributing(cp, cb) : recurseQueryAll(cb);
- }
- }
- void BVHInternalNode::queryAll(Callback::CbFunc const & cb) const
- {
- recurseQueryAll(cb);
- }
- BVHInternalNode::BV BVHInternalNode::getBV() const
- {
- return _bv;
- }
- BVHInternalNode::Type BVHInternalNode::minSquaredDist(Vector const & point) const
- {
- return _bv.minSquaredDist(point);
- }
- BVHInternalNode::Type BVHInternalNode::dist(Ray const & ray) const
- {
- return minSquaredDist(ray.origin());
- }
- void BVHInternalNode::destroy(BVHNodePool& pool)
- {
- pool.destroy(this);
- }
- BVHInternalNode::Type BVHInternalNode::cost(BV const & bv) const
- {
- return _bv.cost(bv);
- }
- void BVHInternalNode::insert(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool)
- {
- insert(info);
- auto& child = childToDescend(info.bv());
- child->insert(info, child, node_pool);
- }
- bool BVHInternalNode::remove(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted)
- {
- bool dirty = false;
- if (_bv.intersects(info.bv())) {
- bool deleted_left = false;
- dirty = dirty || _left->remove(info, _left, node_pool, deleted_left);
- bool deleted_right = false;
- dirty = dirty || _right->remove(info, _right, node_pool, deleted_right);
- if (deleted_left) {
- rebuild(this_ptr, _right, node_pool);
- }
- else if (deleted_right) {
- rebuild(this_ptr, _left, node_pool);
- }
- }
- if (dirty) {
- markAsDirty();
- }
- return dirty;
- }
- bool BVHInternalNode::removeIfDoesNotFit(PrimitiveInfo const & info, BV const & bv_old, BVHNode const * parent, BVHNode const * root, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted)
- {
- bool dirty = false;
- if (_bv.intersects(bv_old)) {
- bool deleted_left = false;
- dirty = dirty || _left->removeIfDoesNotFit(info, bv_old, this, root, _left, node_pool, deleted_left);
- bool deleted_right = false;
- dirty = dirty || _right->removeIfDoesNotFit(info, bv_old, this, root, _right, node_pool, deleted_right);
- if (deleted_left) {
- rebuild(this_ptr, _right, node_pool);
- }
- else if (deleted_right) {
- rebuild(this_ptr, _left, node_pool);
- }
- }
- if (dirty) {
- markAsDirty();
- }
- return dirty;
- }
- void BVHInternalNode::destroyTree(StackTrivial<PrimitiveInfo>& primitives, BVHNodePool& node_pool)
- {
- _left->destroyTree(primitives, node_pool);
- _right->destroyTree(primitives, node_pool);
- destroy(node_pool);
- }
- BVHInternalNode::DirtyInfo BVHInternalNode::recalculateDirty()
- {
- if (isDirty()) {
- collectFromChildren(_left->recalculateDirty());
- collectFromChildren(_right->recalculateDirty());
- }
- return { _bv, _minSquaredSize, _maxSquaredSize };
- }
- size_t BVHInternalNode::minHeight(size_t const & height) const
- {
- return std::min(_left->minHeight(height + 1u), _right->minHeight(height + 1u));
- }
- size_t BVHInternalNode::maxHeight(size_t const & height) const
- {
- return std::max(_left->maxHeight(height + 1u), _right->maxHeight(height + 1u));
- }
- void BVHInternalNode::averageHeight(float const & height, float const & inv_num_leafs, float& avg_height) const
- {
- _left->averageHeight(height + 1.f, inv_num_leafs, avg_height);
- _right->averageHeight(height + 1.f, inv_num_leafs, avg_height);
- }
- void BVHInternalNode::insert(BVHInternalNode::PrimitiveInfo const & pi)
- {
- _bv.unify(pi.bv());
- Algorithm::minimize(pi.squaredSize(), _minSquaredSize);
- Algorithm::maximize(pi.squaredSize(), _maxSquaredSize);
- }
- BVHInternalNode::NodePtr& BVHInternalNode::childToDescend(BV const & bv)
- {
- return _left->cost(bv) < _right->cost(bv) ? _left : _right;
- }
- void BVHInternalNode::markAsDirty()
- {
- _bv = BV();
- _minSquaredSize = std::numeric_limits<Type>::max();
- _maxSquaredSize = std::numeric_limits<Type>::lowest();
- }
- bool BVHInternalNode::isDirty() const
- {
- return _maxSquaredSize == std::numeric_limits<Type>::lowest();
- }
- void BVHInternalNode::rebuild(NodePtr& this_ptr, NodePtr child, BVHNodePool& node_pool)
- {
- StackTrivial<PrimitiveInfo> infos;
- child->destroyTree(infos, node_pool);
- this_ptr = node_pool.createNode(infos);
- destroy(node_pool);
- }
- void BVHInternalNode::collectFromChildren(DirtyInfo const & di)
- {
- _bv.unify(di.bv());
- Algorithm::minimize(di.minSquaredSize(), _minSquaredSize);
- Algorithm::maximize(di.maxSquaredSize(), _maxSquaredSize);
- }
- void BVHInternalNode::descendVisible(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendVisible(*this, cp, cb);
- }
- void BVHInternalNode::descendVisible(CsmInternalNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- if (contributes(cp)) {
- if (auto const result = IntersectionTests::intersectFrustum(_bv, other.frustumPlanes())) {
- if (result.intersecting()) {
- _bv.largerThan(other.bvRender()) ? recurseVisible(other, cp, cb) : other.recurseVisible(*this, cp, cb);
- }
- else {
- _bv.largerThan(other.bvRender()) ? recurseContributing(other, cp, cb) : other.recurseContributing(*this, cp, cb);
- }
- }
- }
- }
- void BVHInternalNode::descendVisible(CsmLeafNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- if (contributes(cp)) {
- if (auto const result = IntersectionTests::intersectFrustum(_bv, other.split().frustumPlanes())) {
- result.intersecting() ? recurseVisible(other, cp, cb) : recurseContributing(other, cp, cb);
- }
- }
- }
- void BVHInternalNode::descendContributing(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendContributing(*this, cp, cb);
- }
- void BVHInternalNode::descendContributing(CsmInternalNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- if (auto const result = computeContribution(cp)) {
- if (result.intersecting()) {
- _bv.largerThan(other.bvRender()) ? recurseContributing(other, cp, cb) : other.recurseContributing(*this, cp, cb);
- }
- else {
- descendAll(other, cb.onRender());
- }
- }
- }
- void BVHInternalNode::descendContributing(CsmLeafNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- if (auto const result = computeContribution(cp)) {
- result.intersecting() ? recurseContributing(other, cp, cb) : descendAll(other, cb.onRender());
- }
- }
- void BVHInternalNode::descendAll(Descendable & other, Callback2::CbFunc const & on_render)
- {
- other.descendAll(*this, on_render);
- }
- void BVHInternalNode::descendAll(CsmInternalNode & other, Callback2::CbFunc const & on_render)
- {
- recurseAll(other, on_render);
- }
- void BVHInternalNode::descendAll(CsmLeafNode & other, Callback2::CbFunc const & on_render)
- {
- recurseAll(other, on_render);
- }
- void BVHInternalNode::recurseVisible(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- _left->descendVisible(other, cp, cb);
- _right->descendVisible(other, cp, cb);
- }
- void BVHInternalNode::recurseContributing(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- _left->descendContributing(other, cp, cb);
- _right->descendContributing(other, cp, cb);
- }
- void BVHInternalNode::recurseAll(Descendable & other, Callback2::CbFunc const & on_render)
- {
- _left->descendAll(other, on_render);
- _right->descendAll(other, on_render);
- }
- }
- #include <BVHLeafNode.h>
- #include <BVHInternalNode.h>
- #include <BVHNodePool.h>
- #include <StackTrivial.h>
- #include <CullingParams.h>
- #include <CsmInternalNode.h>
- #include <CsmLeafNode.h>
- namespace Log2
- {
- BVHLeafNode::BVHLeafNode(Primitive* const & primitive)
- : BVHNode(),
- _primitive(primitive)
- {
- }
- void BVHLeafNode::cullVisiblePrimitives(CullingParams const & cp, Callback const & cb) const
- {
- cb.onIntersectFrustum()(_primitive);
- }
- void BVHLeafNode::cullVisiblePrimitives(CullingParams const & cp, IntersectedPlanes const & in, Callback const & cb) const
- {
- cb.onIntersectFrustum()(_primitive);
- }
- void BVHLeafNode::cullContributingPrimitives(CullingParams const & cp, Callback const & cb) const
- {
- cb.onBecameFullyVisible()(_primitive);
- }
- void BVHLeafNode::cullAllPrimitives(Callback::CbFunc const & on_render) const
- {
- on_render(_primitive);
- }
- size_t BVHLeafNode::sizeInBytes() const
- {
- return sizeof *this;
- }
- void BVHLeafNode::intersectNested(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, std::function<void(Primitive const *)> const & intersect_nested) const
- {
- Type t_first;
- if (getBV().intersects(bv, v, v_inv, t_first) && t_first < min_t_first) {
- intersect_nested(_primitive);
- }
- }
- void BVHLeafNode::intersectPrimitives(BV const & bv, Vector const & v, Vector const & v_inv, Type& min_t_first, Primitive const *& nearest) const
- {
- Type t_first;
- if (getBV().intersects(bv, v, v_inv, t_first) && t_first < min_t_first) {
- min_t_first = t_first;
- nearest = _primitive;
- }
- }
- void BVHLeafNode::countNodes(unsigned& internal_nodes, unsigned& leaf_nodes) const
- {
- ++leaf_nodes;
- }
- void BVHLeafNode::findNearest(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive const *& nearest, Type& nearest_t, Matrix const *& nearest_transform) const
- {
- if (auto const result = IntersectionTests::intersectRay(getBV(), ray_local)) {
- auto const t_world = distance(ray_world.origin(), MathHelpers::transformPoint(*transform, ray_local.pos(result.t())));
- if (t_world < nearest_t) {
- nearest = _primitive;
- nearest_t = t_world;
- nearest_transform = transform;
- }
- }
- }
- void BVHLeafNode::findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res)
- {
- if (IntersectionTests::continueSearch(getBV(), ray_local, ray_world, *transform, res)) {
- if (auto const result = _primitive->intersectRay(ray_local, ray_world, *transform)) {
- if (result.t() < res.nearestT()) {
- res.update(result, transform, _primitive);
- }
- }
- }
- }
- void BVHLeafNode::findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, Primitive* parent, IntersectRayResult& res, Primitive*& parent_res)
- {
- if (IntersectionTests::continueSearch(getBV(), ray_local, ray_world, *transform, res)) {
- if (auto const result = _primitive->intersectRay(ray_local, ray_world, *transform)) {
- if (result.t() < res.nearestT()) {
- res.update(result, transform, _primitive);
- parent_res = parent;
- }
- }
- }
- }
- void BVHLeafNode::findNearestPrecise(Ray const & ray_local, Ray const & ray_world, Matrix const * transform, IntersectRayResult& res, StackTrivial<NodePtr>& stack)
- {
- findNearestPrecise(ray_local, ray_world, transform, res);
- }
- void BVHLeafNode::findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested)
- {
- find_nested(_primitive);
- }
- void BVHLeafNode::findNearestNested(Ray const & ray, IntersectRayResult& res, std::function<void(Primitive*)> const & find_nested, StackTrivial<NodePtr>& stack)
- {
- findNearestNested(ray, res, find_nested);
- }
- void BVHLeafNode::queryRange(BV const & bv, Callback::CbFunc const & cb) const
- {
- if (bv.intersects(getBV())) {
- cb(_primitive);
- }
- }
- void BVHLeafNode::queryRange(BV const & bv, CullingParams const & cp, Callback::CbFunc const & cb) const
- {
- if (contributes(cp) && bv.intersects(getBV())) {
- cb(_primitive);
- }
- }
- void BVHLeafNode::queryContributing(CullingParams const & cp, Callback::CbFunc const & cb) const
- {
- if (contributes(cp)) {
- cb(_primitive);
- }
- }
- void BVHLeafNode::queryAll(Callback::CbFunc const & cb) const
- {
- cb(_primitive);
- }
- BVHLeafNode::BV BVHLeafNode::getBV() const
- {
- return _primitive->bv();
- }
- BVHLeafNode::Type BVHLeafNode::minSquaredDist(Vector const & point) const
- {
- return getBV().minSquaredDist(point);
- }
- BVHLeafNode::Type BVHLeafNode::dist(Ray const & ray) const
- {
- return minSquaredDist(ray.origin());
- }
- void BVHLeafNode::destroy(BVHNodePool& pool)
- {
- pool.destroy(this);
- }
- BVHLeafNode::Type BVHLeafNode::cost(BV const & bv) const
- {
- return getBV().cost(bv);
- }
- void BVHLeafNode::insert(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool)
- {
- PrimitiveInfo infos[2] = { info, _primitive };
- this_ptr = node_pool.createNode(infos, infos + 2);
- destroy(node_pool);
- }
- bool BVHLeafNode::remove(PrimitiveInfo const & info, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted)
- {
- deleted = info.primitive() == _primitive;
- if (deleted) {
- destroy(node_pool);
- }
- return deleted;
- }
- bool BVHLeafNode::removeIfDoesNotFit(PrimitiveInfo const & info, BV const & bv_old, BVHNode const * parent, BVHNode const * root, NodePtr& this_ptr, BVHNodePool& node_pool, bool& deleted)
- {
- deleted = this != root && info.primitive() == _primitive && !parent->getBV().contains(info.bv());
- if (deleted) {
- destroy(node_pool);
- }
- return deleted;
- }
- void BVHLeafNode::destroyTree(StackTrivial<PrimitiveInfo>& primitives, BVHNodePool& node_pool)
- {
- primitives.push_back(_primitive);
- destroy(node_pool);
- }
- BVHLeafNode::DirtyInfo BVHLeafNode::recalculateDirty()
- {
- return { _primitive->bv(), _primitive->squaredSize(), _primitive->squaredSize() };
- }
- size_t BVHLeafNode::minHeight(size_t const & height) const
- {
- return height;
- }
- size_t BVHLeafNode::maxHeight(size_t const & height) const
- {
- return height;
- }
- void BVHLeafNode::averageHeight(float const & height, float const & inv_num_leafs, float& avg_height) const
- {
- avg_height += height * inv_num_leafs;
- }
- void BVHLeafNode::descendVisible(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendVisible(*this, cp, cb);
- }
- void BVHLeafNode::descendVisible(CsmInternalNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- if (contributes(cp)) {
- if (auto const result = IntersectionTests::intersectFrustum(getBV(), other.frustumPlanes())) {
- result.intersecting() ? other.recurseVisible(*this, cp, cb) : other.recurseContributing(*this, cp, cb);
- }
- }
- }
- void BVHLeafNode::descendVisible(CsmLeafNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- cb.onIntersectFrustum()(_primitive, other.split().renderlist());
- }
- void BVHLeafNode::descendContributing(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendContributing(*this, cp, cb);
- }
- void BVHLeafNode::descendContributing(CsmInternalNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- if (contributes(cp)) {
- other.recurseContributing(*this, cp, cb);
- }
- }
- void BVHLeafNode::descendContributing(CsmLeafNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- cb.onBecameFullyVisible()(_primitive, other.split().renderlist());
- }
- void BVHLeafNode::descendAll(Descendable & other, Callback2::CbFunc const & on_render)
- {
- other.descendAll(*this, on_render);
- }
- void BVHLeafNode::descendAll(CsmInternalNode & other, Callback2::CbFunc const & on_render)
- {
- other.recurseAll(*this, on_render);
- }
- void BVHLeafNode::descendAll(CsmLeafNode & other, Callback2::CbFunc const & on_render)
- {
- on_render(_primitive, other.split().renderlist());
- }
- bool BVHLeafNode::contributes(CullingParams const & cp) const
- {
- return getBV().contributes(cp.camPos(), cp.thresh());
- }
- IntersectResult BVHLeafNode::intersectFrustum(CullingParams const & cp) const
- {
- return IntersectionTests::intersectFrustum(getBV(), cp.frustumPlanes());
- }
- }
- #include <CsmInternalNode.h>
- #include <CsmNodePool.h>
- #include <CsmSplit.h>
- #include <CsmNode.h>
- #include <BVHInternalNode.h>
- #include <BVHLeafNode.h>
- #include <CsmTree.h>
- namespace Log2
- {
- CsmInternalNode::CsmInternalNode(CsmSplit * const begin, CsmSplit * const end, CsmTree & np, Matrix<4, 4, Type> const & view_matrix_light) :
- _bvCull(begin->bvCull()),
- _bvRender(begin->bvRender())
- {
- for (auto const * ptr = begin + 1u; ptr != end; ) {
- _bvCull.unify(ptr->bvCull());
- _bvRender.unify(ptr->bvRender());
- ++ptr;
- }
- _fp = FrustumPlanes<3, Type>::create(MathHelpers::projectionMatrixOrtho(_bvCull) * view_matrix_light);
- auto axis = _bvRender.longestAxis();
- auto center = _bvRender.center(axis);
- auto* const mid = Algorithm::partitionForceSplit(begin, end, [&axis, ¢er](CsmSplit const & split) {
- return split.bvRender().center(axis) < center;
- });
- _left = np.createNode(begin, mid, view_matrix_light);
- _right = np.createNode(mid, end, view_matrix_light);
- }
- CsmInternalNode::~CsmInternalNode()
- {
- delete _left;
- delete _right;
- }
- FrustumPlanes<3, CsmInternalNode::Type> const & CsmInternalNode::frustumPlanes() const
- {
- return _fp;
- }
- void CsmInternalNode::recurseVisible(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- _left->descendVisible(other, cp, cb);
- _right->descendVisible(other, cp, cb);
- }
- void CsmInternalNode::recurseContributing(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- _left->descendContributing(other, cp, cb);
- _right->descendContributing(other, cp, cb);
- }
- void CsmInternalNode::recurseAll(Descendable & other, Callback2::CbFunc const & on_render)
- {
- _left->descendAll(other, on_render);
- _right->descendAll(other, on_render);
- }
- CsmInternalNode::BV const & CsmInternalNode::bvRender() const
- {
- return _bvRender;
- }
- CsmInternalNode::BV const & CsmInternalNode::bvCull() const
- {
- return _bvCull;
- }
- void CsmInternalNode::descendVisible(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendVisible(*this, cp, cb);
- }
- void CsmInternalNode::descendVisible(BVHInternalNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendVisible(*this, cp, cb);
- }
- void CsmInternalNode::descendVisible(BVHLeafNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendVisible(*this, cp, cb);
- }
- void CsmInternalNode::descendContributing(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendContributing(*this, cp, cb);
- }
- void CsmInternalNode::descendContributing(BVHInternalNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendContributing(*this, cp, cb);
- }
- void CsmInternalNode::descendContributing(BVHLeafNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendContributing(*this, cp, cb);
- }
- void CsmInternalNode::descendAll(Descendable & other, Callback2::CbFunc const & on_render)
- {
- other.descendAll(*this, on_render);
- }
- void CsmInternalNode::descendAll(BVHInternalNode & other, Callback2::CbFunc const & on_render)
- {
- other.descendAll(*this, on_render);
- }
- void CsmInternalNode::descendAll(BVHLeafNode & other, Callback2::CbFunc const & on_render)
- {
- other.descendAll(*this, on_render);
- }
- }
- #include <CsmLeafNode.h>
- #include <BVHInternalNode.h>
- #include <BVHLeafNode.h>
- namespace Log2
- {
- CsmLeafNode::CsmLeafNode(CsmSplit * split) :
- _split(split)
- {
- }
- void CsmLeafNode::descendVisible(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendVisible(*this, cp, cb);
- }
- void CsmLeafNode::descendVisible(BVHInternalNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendVisible(*this, cp, cb);
- }
- void CsmLeafNode::descendVisible(BVHLeafNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendVisible(*this, cp, cb);
- }
- void CsmLeafNode::descendContributing(Descendable & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendContributing(*this, cp, cb);
- }
- void CsmLeafNode::descendContributing(BVHInternalNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendContributing(*this, cp, cb);
- }
- void CsmLeafNode::descendContributing(BVHLeafNode & other, CullingParams const & cp, Callback2 const & cb)
- {
- other.descendContributing(*this, cp, cb);
- }
- void CsmLeafNode::descendAll(Descendable & other, Callback2::CbFunc const & on_render)
- {
- other.descendAll(*this, on_render);
- }
- void CsmLeafNode::descendAll(BVHInternalNode & other, Callback2::CbFunc const & on_render)
- {
- other.descendAll(*this, on_render);
- }
- void CsmLeafNode::descendAll(BVHLeafNode & other, Callback2::CbFunc const & on_render)
- {
- other.descendAll(*this, on_render);
- }
- CsmSplit& CsmLeafNode::split()
- {
- return *_split;
- }
- }
- #include <CsmSplit.h>
- namespace Log2
- {
- CsmSplit::CsmSplit(BV const & bv_light_cull, BV const & bv_light_render, Matrix<4, 4, Type> const & view_matrix_light, Matrix<4, 4, Type>* vp) :
- _bvLightCull(bv_light_cull),
- _bvLightRender(bv_light_render),
- _vp(vp)
- {
- init(view_matrix_light);
- }
- CsmSplit::BV const & CsmSplit::bvCull() const
- {
- return _bvLightCull;
- }
- CsmSplit::BV const & CsmSplit::bvRender() const
- {
- return _bvLightRender;
- }
- Matrix<4, 4, CsmSplit::Type> const & CsmSplit::vp() const
- {
- return *_vp;
- }
- FrustumPlanes<3, CsmSplit::Type> const & CsmSplit::frustumPlanes() const
- {
- return _fp;
- }
- RenderList & CsmSplit::renderlist()
- {
- return _rl;
- }
- void CsmSplit::set(BV const & bv_light_cull, BV const & bv_light_render, Matrix<4, 4, Type> const & view_matrix_light, Matrix<4, 4, Type>* vp)
- {
- _bvLightCull = bv_light_cull;
- _bvLightRender = bv_light_render;
- _vp = vp;
- init(view_matrix_light);
- }
- void CsmSplit::init(Matrix<4, 4, Type> const & view_matrix_light)
- {
- *_vp = MathHelpers::projectionMatrixOrtho(_bvLightCull) * view_matrix_light;
- _fp = FrustumPlanes<3, Type>::create(*_vp);
- }
- }
- #include <CsmTree.h>
- #include <BoundingVolumeHierarchy.h>
- #include <CsmInternalNode.h>
- #include <CsmLeafNode.h>
- namespace Log2
- {
- CsmTree::CsmTree(CsmSplit * begin, CsmSplit * end, Matrix<4, 4, Type> const & view_matrix_light)
- {
- _root = createNode(begin, end, view_matrix_light);
- }
- CsmTree::~CsmTree()
- {
- delete _root;
- }
- CsmNode * CsmTree::root()
- {
- return _root;
- }
- void CsmTree::descendVisible(BoundingVolumeHierarchy& bvh, CullingParams const & cp, Callback2 const & cb)
- {
- _root->descendVisible(*bvh.root(), cp, cb);
- }
- CsmNode * CsmTree::createNode(CsmSplit * begin, CsmSplit * end, Matrix<4, 4, Type> const & view_matrix_light)
- {
- return Algorithm::continueSplit(begin, end) ? createInternalNode(begin, end, view_matrix_light) : createLeafNode(begin);
- }
- CsmNode * CsmTree::createInternalNode(CsmSplit * begin, CsmSplit * end, Matrix<4, 4, Type> const & view_matrix_light)
- {
- return new CsmInternalNode(begin, end, *this, view_matrix_light);
- }
- CsmNode * CsmTree::createLeafNode(CsmSplit * cs)
- {
- return new CsmLeafNode(cs);
- }
- }
- #include <FixedTimestepSystem.h>
- #include <GameTimer.h>
- #include <iostream>
- namespace Log2
- {
- bool FixedTimestepSystem::update()
- {
- _acc += _gameTimer->getDeltaTimeSeconds();
- bool did_update = false;
- while (_acc >= _dt) {
- updateSystem();
- _acc -= _dt;
- did_update = true;
- }
- return did_update;
- }
- }
- #define GLM_ENABLE_EXPERIMENTAL
- #include "Mesh.h"
- #include <fstream>
- #include <sstream>
- #include <iostream>
- #include <glm/gtx/string_cast.hpp>
- #include <AABB.h>
- #include <math/Log2Math.h>
- namespace Log2
- {
- Mesh::Mesh(StackTrivial<Vertex>&& vertices, StackTrivial<unsigned int>&& indices, std::shared_ptr<Material> const * materials, unsigned int material_index) :
- _vertices(std::move(vertices)),
- _indices(std::move(indices)),
- _material(*(materials + material_index)),
- _materialIndex(material_index)
- {
- init();
- }
- StackTrivial<Vertex> const & Mesh::vertices() const
- {
- return _vertices;
- }
- StackTrivial<unsigned int> const & Mesh::indices() const
- {
- return _indices;
- }
- void Mesh::setVertices(StackTrivial<Vertex>&& vertices)
- {
- _vertices = std::move(vertices);
- init();
- }
- void Mesh::setIndices(StackTrivial<unsigned>&& indices)
- {
- _indices = std::move(indices);
- init();
- }
- unsigned const & Mesh::materialIndex() const
- {
- return _materialIndex;
- }
- AABB3f const & Mesh::aabb() const
- {
- return _aabb;
- }
- Sphere3f const & Mesh::sphere() const
- {
- return _sphere;
- }
- void Mesh::setMaterialIndex(unsigned const & material_index)
- {
- _materialIndex = material_index;
- }
- void Mesh::setMaterial(std::shared_ptr<Material> const & material)
- {
- _material = material;
- }
- std::shared_ptr<Material> const & Mesh::material() const
- {
- return _material;
- }
- BoundingVolumeHierarchy * Mesh::bvh()
- {
- return _bvh.get();
- }
- void Mesh::triangles(Vertex * vertices, boost::object_pool<Triangle>& tri_pool, StackTrivial<Primitive*>& triangles) const
- {
- triangles.reserveToFit(_indices.size() / 3u);
- auto const * begin = _indices.begin();
- auto const * end = _indices.end();
- while (begin != end) {
- triangles.push_back_unchecked(new (tri_pool.malloc()) Triangle(Vec3u(*begin, *(begin + 1), *(begin + 2)), vertices));
- begin += 3;
- }
- }
- std::shared_ptr<BoundingVolumeHierarchy> Mesh::getTransformedBVH(Matrix<4, 4, Type> const & transform,
- Matrix<3, 3, Type> const & m_inv_transpose, boost::object_pool<Triangle>& tri_pool, StackTrivial<Vertex>& vertices) const
- {
- vertices.clear();
- vertices.reserve(_vertices.size());
- for (auto const * ptr = _vertices.begin(); ptr != _vertices.end();) {
- vertices.push_back_unchecked(Vertex(MathHelpers::transformPoint(transform, ptr->position()), CompressedNormal(m_inv_transpose * ptr->normal()), ptr->uv(),
- CompressedNormal(m_inv_transpose * ptr->tangent())));
- ++ptr;
- }
- StackTrivial<Primitive*> tris;
- triangles(vertices.begin(), tri_pool, tris);
- return std::make_shared<BoundingVolumeHierarchy>(tris.begin(), tris.end());
- }
- void Mesh::calculateTangentSpace()
- {
- auto * const s = new VertexUncompressed[_vertices.size()]();
- for (auto const * index = _indices.begin(); index != _indices.end(); index += 3) {
- auto& v0 = _vertices[*index];
- auto& v1 = _vertices[*(index + 1)];
- auto& v2 = _vertices[*(index + 2)];
- auto const & uv0 = v0.uv();
- auto const & uv1 = v1.uv();
- auto const & uv2 = v2.uv();
- auto const s1 = uv1.u() - uv0.u();
- auto const t1 = uv1.v() - uv0.v();
- auto const s2 = uv2.u() - uv0.u();
- auto const t2 = uv2.v() - uv0.v();
- auto const one_over_det = s1 * t2 - t1 * s2;
- auto const e1 = v1.position() - v0.position();
- auto const e2 = v2.position() - v0.position();
- auto t = (e1 * t2 - e2 * t1) * one_over_det;
- auto b = (e2 * s1 - e1 * s2) * one_over_det;
- auto n = cross(e1, e2);
- s[*index].add(t, b, n);
- s[*(index + 1)].add(t, b, n);
- s[*(index + 2)].add(t, b, n);
- }
- auto* ptr = s;
- for (auto& v : _vertices) {
- v.set(ptr->t() - ptr->n() * dot(ptr->n(), ptr->t()), dot(cross(ptr->t(), ptr->b()), ptr->n()) < 0.f ? -1 : 1, ptr->n());
- ++ptr;
- }
- delete[] s;
- }
- void Mesh::init()
- {
- calculateTangentSpace();
- _aabb = AABB3f(*this);
- _sphere = Sphere3f(*this);
- StackTrivial<Primitive*> tris;
- triangles(_vertices.begin(), _trianglePool, tris);
- _bvh = std::make_unique<BoundingVolumeHierarchy>(tris.begin(), tris.end());
- }
- }
- #include <Triangle.h>
- #include <Camera.h>
- #include <physics/Particle.h>
- namespace Log2
- {
- Triangle::BV Triangle::bv() const
- {
- return BV::fromVertices<3>(getVertices().data());
- }
- Triangle::Type Triangle::squaredSize() const
- {
- return bv().squaredSize();
- }
- Triangle::Ray::IntersectionResult Triangle::intersectRay(Ray const & ray, Vector<3, Type> const & p0, Vector<3, Type> const & p1, Vector<3, Type> const & p2)
- {
- Ray::IntersectionResult res;
- auto e1 = p1 - p0;
- auto e2 = p2 - p0;
- auto d = ray.dir();
- auto det_a = e1.x() * (-d.z() * e2.y() + d.y() * e2.z()) - e2.x() * (-d.z() * e1.y() + d.y() * e1.z()) - d.x() * (e1.y() * e2.z() - e2.y() * e1.z());
- if (det_a <= -std::numeric_limits<Type>::epsilon() || det_a >= std::numeric_limits<Type>::epsilon()) {
- auto one_over_det = static_cast<Type>(1) / det_a;
- auto s = ray.origin() - p0;
- res.setU(dot(Vector<3, Type>(-d.z() * e2.y() + d.y() * e2.z(), d.z() * e2.x() - d.x() * e2.z(), -d.y() * e2.x() + d.x() * e2.y()), s) * one_over_det);
- if (res.uv().validU()) {
- res.setV(dot(Vector<3, Type>(d.z() * e1.y() - d.y() * e1.z(), -d.z() * e1.x() + d.x() * e1.z(), d.y() * e1.x() - d.x() * e1.y()), s) * one_over_det);
- if (res.uv().validVW()) {
- res.setT(dot(Vector<3, Type>(e1.y() * e2.z() - e2.y() * e1.z(), -e1.x() * e2.z() + e2.x() * e1.z(), e1.x() * e2.y() - e2.x() * e1.y()), s) * one_over_det);
- return res;
- }
- }
- }
- return res;
- }
- Triangle::Ray::IntersectionResult Triangle::intersectRay(Ray const & ray_local, Ray const & ray_world, Matrix const & mat)
- {
- if (auto res = intersectRay(ray_local)) {
- res.setT(distance(ray_world.origin(), MathHelpers::transformPoint(mat, ray_local.pos(res.t()))));
- return res;
- }
- return Triangle::Ray::IntersectionResult();
- }
- Triangle::Ray::IntersectionResult Triangle::intersectRay(Ray const & ray)
- {
- return intersectRay(ray, vertex<0>(), vertex<1>(), vertex<2>());
- }
- Triangle::Ray::IntersectionResult Triangle::intersectRay(Ray const & ray, Matrix const & mat)
- {
- return intersectRay(ray, MathHelpers::transformPoint(mat, vertex<0>()), MathHelpers::transformPoint(mat, vertex<1>()), MathHelpers::transformPoint(mat, vertex<2>()));
- }
- void Triangle::debugTriangle(Vector<4, Type> * _debugTriangle, Matrix const & transform) const
- {
- *_debugTriangle++ = transform * vertex<0>().toHomogeneous();
- *_debugTriangle++ = transform * vertex<1>().toHomogeneous();
- *_debugTriangle = transform * vertex<2>().toHomogeneous();
- }
- Triangle * Triangle::toTriangle()
- {
- return this;
- }
- }
- #include <opengl/GLSLShaderGenerator.h>
- #include <GraphicsSettings.h>
- #include <Flags.h>
- #include <iostream>
- namespace Log2
- {
- GLSLShaderGenerator::GLSLShaderGenerator() :
- _compositeVertexSource(std::string(vertexFileComposite), GL_VERTEX_SHADER)
- {
- _windParamString = "uniform float " + std::string(time) + "; \n\
- uniform vec3 " + std::string(bbMin) + "; // AABB min xz\n\
- uniform vec3 " + std::string(bbMax) + "; // AABB max xz\n" + std::string(noiseCodeGLSL());
- _springParticleDataStr = "layout (std430, binding = " + str(bufferBindingSpringSkinnedInitPos) + ") readonly buffer init_pos_buffer \n\
- { \n\
- vec4 init_pos[]; \n\
- };\n\
- layout(std430, binding = " + str(bufferBindingSpringSkinnedPos) + ") readonly buffer pos_buffer \n\
- { \n\
- vec4 pos[]; \n\
- };\n";
- }
- GLShaderSource GLSLShaderGenerator::createMeshVertexShaderSource(unsigned const & flags, GraphicsSettings const & gs)const
- {
- std::string key = "vs";
- if (flags & MeshRenderFlag::MR_SPRING_SKINNED) {
- key += "_spring_skinned";
- }
- key += ".glsl";
- GLShaderSource src;
- src._key = key;
- src._source = createMeshVertexSource(flags, gs);
- src._type = GL_VERTEX_SHADER;
- return src;
- }
- GLShaderSource GLSLShaderGenerator::createMeshFragmentShaderSource(unsigned const & flags, GraphicsSettings const & gs)const
- {
- std::string key = "fs";
- if (flags & MeshRenderFlag::MR_DIFFUSE_MAP) {
- key += "_albedo";
- }
- if (flags & MeshRenderFlag::MR_NORMAL_MAP) {
- key += "_normal";
- if (flags & MeshRenderFlag::MR_HEIGHT_MAP) {
- key += "_parallax";
- }
- }
- if (flags & MeshRenderFlag::MR_ALPHA_MAP) {
- key += "_alpha";
- }
- if (flags & MeshRenderFlag::MR_REFLECTIVE) {
- key += "_reflective";
- }
- if (gs.screenSpaceReflections()) {
- key += "_ssr";
- }
- if (gs.shadows() || gs.shadowsPCF()) {
- key += "_shadows";
- }
- if (gs.shadowsPCF()) {
- key += "_pcf";
- }
- if (gs.softShadows()) {
- key += "_soft_shadows";
- }
- if (gs.gammaEnabled()) {
- key += "_gamma";
- }
- key += ".glsl";
- GLShaderSource src;
- src._key = key;
- src._source = createMeshFragmentSource(flags, gs);
- src._type = GL_FRAGMENT_SHADER;
- return src;
- }
- GLShaderSource GLSLShaderGenerator::createMeshVertexShaderDepthSource(unsigned const & flags, GraphicsSettings const & gs)const
- {
- std::string key = "vs_depth";
- if (flags & MeshRenderFlag::MR_SPRING_SKINNED) {
- key += "_spring_skinned";
- }
- key += ".glsl";
- GLShaderSource src;
- src._key = key;
- src._source = createMeshVertexDepthSource(flags, gs);
- src._type = GL_VERTEX_SHADER;
- return src;
- }
- GLShaderSource GLSLShaderGenerator::createMeshFragmentShaderDepthSource(unsigned const & flags, GraphicsSettings const & gs)const
- {
- std::string key = "fs_depth";
- if (flags & MeshRenderFlag::MR_ALPHA_MAP) {
- key += "_alpha";
- }
- key += ".glsl";
- GLShaderSource src;
- src._key = key;
- src._source = createMeshFragmentDepthSource(flags, gs);
- src._type = GL_FRAGMENT_SHADER;
- return src;
- }
- void GLSLShaderGenerator::createCompositeShaderSource(GraphicsSettings const & gs, GLShaderSource& vertex_src, GLShaderSource& fragment_src, bool god_rays)const
- {
- vertex_src = _compositeVertexSource;
- std::string key = "fs_composite";
- if (gs.depthOfField()) {
- key += "_dof";
- }
- if (gs.exposureEnabled()) {
- key += "_exposure";
- }
- if (gs.gammaEnabled()) {
- key += "_gamma";
- }
- if (god_rays) {
- key += "_god_rays";
- }
- if (gs.bloom()) {
- key += "_bloom";
- }
- key += ".glsl";
- fragment_src._key = key;
- fragment_src._source = createCompositeShaderSource(gs, god_rays);
- fragment_src._type = GL_FRAGMENT_SHADER;
- }
- void GLSLShaderGenerator::createBlurShaderSource(GraphicsSettings const & gs, GLShaderSource & vertex_src, GLShaderSource & fragment_src)const
- {
- vertex_src = _compositeVertexSource;
- fragment_src._source = "#version 330 \n\
- layout(location = 0) out vec3 fragmentColor;\n\
- in vec2 uv;\n\
- uniform sampler2D " + std::string(toBlurSampler) + ";\n\
- uniform vec2 " + std::string(texelSize) + ";\n";
- fragment_src._source += blurSource(gs.blurWeights(gs.blurRadius(), gs.blurSigma()));
- fragment_src._source += "void main()\n\
- {\n\
- fragmentColor = vec3(0.f);\n\
- for (int i = -" + str(gs.blurRadius()) + "; i <= " + str(gs.blurRadius()) + "; i++){\n\
- fragmentColor += texture(" + std::string(toBlurSampler) + ", uv + i * " + std::string(texelSize) + ").rgb * blur_weights[i + " + str(gs.blurRadius()) + "];\n\
- }\n\
- }\n";
- fragment_src._key = "fs_blur";
- fragment_src._type = GL_FRAGMENT_SHADER;
- }
- void GLSLShaderGenerator::createSSRShaderSource(const GraphicsSettings & gs, GLShaderSource & vertex_src, GLShaderSource & fragment_src)const
- {
- vertex_src = _compositeVertexSource;
- fragment_src._source = "#version 330 \n\
- layout(location = 0) out vec3 fragmentColor;\n\
- in vec2 uv;\n\
- uniform sampler2D " + std::string(lightingSampler) + ";\n\
- uniform sampler2D " + std::string(viewSpaceNormalsSampler) + ";\n\
- uniform sampler2D " + std::string(depthSampler) + ";\n\
- uniform mat4 " + std::string(projectionMatrixInverse) + "; // Inverse projection matrix\n\
- uniform mat4 " + std::string(projectionMatrix) + "; // Projection matrix\n\
- uniform vec4 " + std::string(projectionMatrixInverseThirdRow) + "; // Third row of inverse projection matrix\n\
- uniform vec4 " + std::string(projectionMatrixInverseFourthRow) + "; // Fourth row of inverse projection matrix\n\
- void main()\n\
- {\n\
- vec3 normal_view = textureLod(" + std::string(viewSpaceNormalsSampler) + ", uv, 0.f).xyz;\n\
- if (normal_view != vec3(0.f)) {\n\
- vec4 pos_view_h = " + std::string(projectionMatrixInverse) + " * vec4(vec3(uv, texture(" + std::string(depthSampler) + ", uv).r) * 2.f - 1.f, 1.f);\n\
- vec3 pos_view = pos_view_h.xyz / pos_view_h.w;\n\
- vec3 ray_dir = reflect(normalize(pos_view), normal_view);\n\
- vec3 ray = ray_dir * max(-pos_view.z * " + str(gs.SSRRayLenScale()) + "f, " + str(gs.SSRMinRayLen()) + ");\n\
- vec3 delta = ray / " + str(gs.SSRSteps()) + "f;\n\
- vec3 ray_pos_view = pos_view + delta;\n\
- for (float i = 0.f; i < " + str(gs.SSRSteps()) + "f; i++, ray_pos_view += delta) {\n\
- vec4 ray_pos_h = " + std::string(projectionMatrix) + " * vec4(ray_pos_view, 1.f);\n\
- vec2 ray_pos_ndc = ray_pos_h.xy / ray_pos_h.w;\n\
- vec2 uv = ray_pos_ndc * 0.5f + 0.5f;\n\
- vec4 comp_ndc = vec4(vec3(uv, texture(" + std::string(depthSampler) + ", uv).r) * 2.f - 1.f, 1.f);\n\
- float comp_depth = dot(comp_ndc, " + std::string(projectionMatrixInverseThirdRow) + ") / dot(comp_ndc, " + std::string(projectionMatrixInverseFourthRow) + ");\n\
- if (ray_pos_view.z > comp_depth) { // Intersection found, the ray traveled behind the depth buffer. \n\
- float sign;\n\
- for (uint i = 0u; i < " + str(gs.SSRBinarySteps()) + "u; i++, delta *= 0.5f, ray_pos_view += delta * sign) { // Binary search refinement\n\
- ray_pos_h = " + std::string(projectionMatrix) + " * vec4(ray_pos_view, 1.f);\n\
- ray_pos_ndc = ray_pos_h.xy / ray_pos_h.w;\n\
- uv = ray_pos_ndc * 0.5f + 0.5f;\n\
- vec4 comp_ndc = vec4(vec3(uv, texture(" + std::string(depthSampler) + ", uv).r) * 2.f - 1.f, 1.f);\n\
- float comp_depth = dot(comp_ndc, " + std::string(projectionMatrixInverseThirdRow) + ") / dot(comp_ndc, " + std::string(projectionMatrixInverseFourthRow) + ");\n\
- sign = ray_pos_view.z > comp_depth ? -1.f : 1.f;\n\
- }\n\
- fragmentColor = textureLod(" + std::string(lightingSampler) + ", uv, 0.f).rgb;\n\
- return;\n\
- }\n\
- }\n\
- }\n\
- fragmentColor = textureLod(" + std::string(lightingSampler) + ", uv, 0.f).rgb;\n\
- }\n";
- fragment_src._key = "fs_ssr";
- fragment_src._type = GL_FRAGMENT_SHADER;
- }
- void GLSLShaderGenerator::createGodRayShaderSource(const GraphicsSettings& gs, GLShaderSource & vertex_src, GLShaderSource & fragment_src) const
- {
- vertex_src = _compositeVertexSource;
- fragment_src._source = "#version 330\n\
- layout(location = 0) out vec3 fragmentColor;\n\
- uniform sampler2D " + std::string(lightingSampler) + ";\n\
- uniform sampler2D " + std::string(depthSampler) + ";\n\
- uniform vec2 " + std::string(lightPosUV) + ";\n\
- in vec2 uv;\n\
- void main()\n\
- {\n\
- fragmentColor = vec3(0.f);\n\
- vec2 delta = (" + std::string(lightPosUV) + " - uv) / " + str(gs.godRaySteps()) + ";\n\
- vec2 tex_coord = uv;\n\
- float decay = 1.f;\n\
- for (float i = 0.f; i < " + str(gs.godRaySteps()) + "; i++, tex_coord += delta, decay *= " + str(gs.godRayDecay()) + ") { \n\
- fragmentColor += decay * texture(" + std::string(lightingSampler) + ", tex_coord).rgb * float(texture(" + std::string(depthSampler) + ", tex_coord).r == 1.f);\n\
- }\n\
- fragmentColor /= " + str(gs.godRaySteps()) + ";\n\
- }\n";
- fragment_src._key = "fs_god_ray";
- fragment_src._type = GL_FRAGMENT_SHADER;
- }
- void GLSLShaderGenerator::createBrightnessShaderSource(const GraphicsSettings & gs, GLShaderSource & vertex_src, GLShaderSource & fragment_src) const
- {
- vertex_src = _compositeVertexSource;
- fragment_src._source = "#version 330\n\
- layout (location = 0) out vec3 fragmentColor;\n\
- uniform sampler2D " + std::string(lightingSampler) + ";\n\
- in vec2 uv;\n\
- void main() \n\
- {\n\
- vec3 col = texture(" + std::string(lightingSampler) + ", uv).rgb; \n\
- fragmentColor = col * smoothstep(0.85f, 1.f, dot(col, vec3(0.2126f, 0.7152f, 0.0722f)));\n\
- }";
- fragment_src._type = GL_FRAGMENT_SHADER;
- }
- std::string GLSLShaderGenerator::createMeshVertexSource(unsigned const & flags, GraphicsSettings const & gs) const
- {
- std::string version = (flags & MR_SPRING_SKINNED) ? "450" : "330";
- std::string shader_src;
- shader_src += "#version " + version + "\n\
- layout(location = 0) in vec3 position;\n\
- layout(location = 1) in vec3 normal;\n\
- layout(location = 2) in vec2 uv;\n\
- layout(location = 3) in vec4 tangent;\n\
- layout (location = 4) in uvec4 p_indices;\n\
- layout(location = 5) in vec4 weights;\n\
- // Shader constants\n\
- uniform mat4 VP; \n\
- // Model constants\n\
- uniform mat4 " + std::string(modelMatrix) + ";\n\
- out vec3 pos_world;\n\
- out vec3 normal_local;\n\
- out vec2 uv_out;\n\
- out vec4 tangent_local;\n";
- if (flags & MeshRenderFlag::MR_SPRING_SKINNED) {
- shader_src += _springParticleDataStr;
- }
- if (gs.depthPrepassEnabled()) {
- shader_src += "invariant gl_Position; \n";
- }
- shader_src += "void main()\n\
- {\n";
- if (flags & MeshRenderFlag::MR_SPRING_SKINNED) {
- shader_src += " vec3 offs = vec3(0.f);\n\
- for (uint i = 0; i < 4; i++) { \n\
- offs += (pos[p_indices[i]].xyz - init_pos[p_indices[i]].xyz) * weights[i]; \n\
- }\n";
- shader_src += " pos_world = (" + std::string(modelMatrix) + " * vec4(position + offs, 1.f)).xyz;\n";
- }
- else {
- shader_src += " pos_world = (" + std::string(modelMatrix) + " * vec4(position, 1.f)).xyz;\n";
- }
- shader_src += " gl_Position = VP * vec4(pos_world, 1.f);\n\
- normal_local = normal;\n\
- uv_out = uv;\n\
- tangent_local = tangent;\n";
- shader_src += "}\n";
- return shader_src;
- }
- std::string GLSLShaderGenerator::createMeshVertexDepthSource(unsigned const & flags, GraphicsSettings const & gs) const
- {
- std::string version = (flags & MR_SPRING_SKINNED) ? "450" : "330";
- std::string shader_src = "#version " + version + "\n\
- layout(location = 0) in vec3 position;\n\
- layout(location = 2) in vec2 uv;\n\
- layout(location = 5) in uvec4 p_indices; \n\
- layout(location = 6) in vec4 weights; \n";
- if (gs.depthPrepassEnabled()) {
- shader_src += "invariant gl_Position; \n";
- }
- shader_src += "uniform mat4 " + std::string(modelMatrix) + ";\n";
- shader_src += "uniform mat4 " + std::string(viewProjectionMatrix) + "; \n";
- shader_src += _windParamString;
- shader_src += "out vec2 uv_out;\n";
- if (flags & MR_SPRING_SKINNED) {
- shader_src += _springParticleDataStr;
- }
- shader_src += "void main()\n\
- {\n";
- if (flags & MR_SPRING_SKINNED) {
- shader_src += " vec3 offs = vec3(0.f);\n\
- for (uint i = 0; i < 4; i++) { \n\
- offs += (pos[p_indices[i]].xyz - init_pos[p_indices[i]].xyz) * weights[i]; \n\
- }\n";
- shader_src += " vec4 pos_world = " + std::string(modelMatrix) + " * vec4(position + offs, 1.f);\n";
- }
- else {
- shader_src += " vec4 pos_world = " + std::string(modelMatrix) + " * vec4(position, 1.f);\n";
- }
- shader_src += " gl_Position = " + std::string(viewProjectionMatrix) + " * pos_world;\n";
- shader_src += " uv_out = uv;\n\
- }\n";
- return shader_src;
- }
- std::string GLSLShaderGenerator::createMeshFragmentSource(unsigned const & flags, GraphicsSettings const & gs) const
- {
- std::string version = "330";
- bool tangent_space = (flags & MR_NORMAL_MAP) || (flags & MR_HEIGHT_MAP);
- std::string shader_src = "#version " + version + " \n\
- layout(location = 0) out vec3 fragmentColor;\n";
- unsigned rt_index = 1;
- if (gs.screenSpaceReflections()) {
- shader_src += "layout(location = " + str(rt_index) + ") out vec3 viewSpaceNormal; \n";
- rt_index++;
- }
- shader_src += "in vec3 pos_world;\n\
- in vec2 uv_out;\n\
- uniform vec3 " + std::string(diffuseColor) + ";\n\
- uniform sampler2D " + std::string(diffuseSampler) + ";\n\
- uniform sampler2D " + std::string(alphaSampler) + ";\n\
- uniform sampler2D " + std::string(normalSampler) + ";\n\
- uniform sampler2D " + std::string(heightSampler) + ";\n\
- uniform float " + std::string(parallaxHeightScale) + "; // Parallax ray scale\n\
- uniform float " + std::string(shadowMapBias) + "; // Shadow map bias\n\
- uniform float " + std::string(parallaxMinSteps) + "; // Parallax min steps\n\
- uniform float " + std::string(parallaxMaxSteps) + "; // Parallax max steps\n\
- uniform float " + std::string(parallaxBinarySearchSteps) + "; // Parallax binary search steps\n\
- uniform vec3 " + std::string(lightDirWorld) + "; // light direction world space\n\
- uniform vec3 " + std::string(cameraPositionWorld) + "; // camera position world space\n\
- uniform vec3 " + std::string(lightIntensity) + "; // light intensity\n\
- uniform mat4 " + std::string(worldToLightMatrices) + " [" + str(gs.frustumSplits().size()) + "]; // world space to light space\n\
- uniform float " + std::string(frustumSplits) + " [" + str(gs.frustumSplits().size()) + "]; // frustum_splits\n\
- uniform int " + std::string(numfrustumSplits) + "; // num frustum splits\n";
- shader_src += (gs.shadowsPCF() ? "uniform sampler2DArrayShadow " : "uniform sampler2DArray ") + std::string(shadowSampler) + ";\n";
- shader_src += "// Material constants\n\
- uniform float " + std::string(ambientConstant) + ";\n\
- uniform float " + std::string(diffuseConstant) + ";\n\
- uniform float " + std::string(specularConstant) + ";\n\
- uniform float " + std::string(specularExponent) + ";\n\
- uniform float " + std::string(gamma) + ";\n\
- uniform mat3 " + std::string(modelMatrixTransposeInverse) + ";\n\
- uniform mat3 " + std::string(viewMatrixOrtho) + ";\n\
- uniform vec4 " + std::string(viewMatrixThirdRow) + ";\n\
- in vec3 normal_local;\n\
- in vec4 tangent_local;\n";
- shader_src += blurSource(gs.blurWeights2D(gs.shadowBlurRadius(), gs.shadowBlurSigma()));
- shader_src += "void main()\n\
- {\n\
- vec2 uv = uv_out;\n";
- if (tangent_space) {
- shader_src += " vec3 bitangent_local = tangent_local.w * cross(normal_local, tangent_local.xyz);\n"; // Handedness is stored in the w coordinate of the tangent vector.
- shader_src += " mat3 world_to_tangent = mat3(normalize(" + std::string(modelMatrixTransposeInverse) + " * vec3(tangent_local.x, bitangent_local.x, normal_local.x)), normalize(" + std::string(modelMatrixTransposeInverse) + " * vec3(tangent_local.y, bitangent_local.y, normal_local.y)), normalize(" + std::string(modelMatrixTransposeInverse) + " * vec3(tangent_local.z, bitangent_local.z, normal_local.z)));\n";
- }
- shader_src += " vec3 e =" + std::string(tangent_space ? " world_to_tangent *" : "") + " normalize(" + std::string(cameraPositionWorld) + " - pos_world); \n";
- if ((flags & MR_NORMAL_MAP) && (flags & MR_HEIGHT_MAP)) {
- if (!gs.reliefMapping()) {
- shader_src += " uv -= e.xy / e.z * (1.f - textureLod(" + std::string(heightSampler) + ", uv, 0.f).r) * " + std::string(parallaxHeightScale) + "; \n";
- }
- else {
- shader_src += " float steps = mix(" + std::string(parallaxMaxSteps) + ", " + std::string(parallaxMinSteps) + ", clamp(dot(vec3(0.f, 0.f, 1.f), e), 0.f, 1.f));\n\
- vec2 ray = e.xy * " + std::string(parallaxHeightScale) + ";\n\
- vec2 delta = ray / steps;\n\
- float layer_delta = 1.f / steps;\n\
- float layer_depth = 1.f - layer_delta;\n\
- uv -= delta;\n\
- for (float i = 0.f; i < steps; i++, uv -= delta, layer_depth -= layer_delta) {\n\
- if(textureLod(" + std::string(heightSampler) + ", uv, 0.f).r > layer_depth){\n\
- delta *= 0.5f;\n\
- layer_delta *= 0.5f;\n\
- uv += delta;\n\
- layer_depth += layer_delta;\n\
- for (float i = 0.f, sign; i < " + std::string(parallaxBinarySearchSteps) + "; i++, uv += delta * sign, layer_depth += layer_delta * sign){\n\
- sign = (textureLod(" + std::string(heightSampler) + ", uv, 0.f).r > layer_depth) ? 1.f : -1.f;\n\
- delta *= 0.5f;\n\
- layer_delta *= 0.5f;\n\
- }\n\
- break;\n\
- }\n\
- }\n";
- }
- }
- if (flags & MeshRenderFlag::MR_ALPHA_MAP) {
- shader_src += " if (texture(" + std::string(alphaSampler) + ", uv).r < 0.5f) {\n\
- discard;\n\
- return;\n\
- }\n";
- }
- shader_src += " vec3 l = " + std::string((tangent_space ? "world_to_tangent *" : "")) + std::string(lightDirWorld) + ";\n";
- // std::string normal_str = "normal_world";
- if (flags & MeshRenderFlag::MR_NORMAL_MAP) {
- shader_src += " vec3 n = normalize((texture(" + std::string(normalSampler) + ", uv).xyz * 2.f - 1.f));\n";
- }
- else {
- shader_src += " vec3 n = normalize(" + std::string(modelMatrixTransposeInverse) + " * normal_local);\n";
- }
- shader_src += " float diffuse = max(dot(l, n), 0.f);\n\
- float specular = pow(max(dot(normalize(e + l), n), 0.f), " + std::string(specularExponent) + ");\n";
- if (flags & MeshRenderFlag::MR_DIFFUSE_MAP) {
- shader_src += " vec3 albedo = texture(" + std::string(diffuseSampler) + ", uv).rgb;\n";
- }
- else {
- shader_src += " vec3 albedo = " + std::string(diffuseColor) + ";\n";
- }
- if (gs.gammaEnabled()) {
- shader_src += " albedo = pow(albedo, vec3(" + std::string(gamma) + "));\n";
- }
- if (gs.shadows() || gs.shadowsPCF()) {
- shader_src += " int index = " + std::string(numfrustumSplits) + "-1;\n\
- for (int i = " + std::string(numfrustumSplits) + "-2; i >= 0; i--) {\n\
- index -= int(dot(" + std::string(viewMatrixThirdRow) + ", vec4(pos_world, 1.f)) < " + std::string(frustumSplits) + "[i]);\n\
- }\n";
- shader_src += " vec4 shadow_coord = " + std::string(worldToLightMatrices) + "[index] * vec4(pos_world, 1.f);\n\
- shadow_coord.xyz /= shadow_coord.w;\n\
- shadow_coord = shadow_coord * 0.5f + 0.5f;\n";
- // shadow_coord.z -= " + std::string(shadowMapBias()) + ";\n";
- if (!gs.shadowsPCF()) {
- shader_src += " if (all(greaterThanEqual(shadow_coord.xyz, vec3(0.f))) && all(lessThanEqual(shadow_coord.xyz, vec3(1.f)))) {\n ";
- }
- if (gs.softShadows()) {
- auto rad = str(gs.shadowBlurRadius());
- shader_src += " float light_factor = 1.f;\n\
- vec2 offs = 1.f / textureSize(" + std::string(shadowSampler) + ", 0).xy;\n\
- for (int u = -" + rad + "; u <= " + rad + "; u++) {\n\
- for(int v = -" + rad + "; v <= " + rad + "; v++) {\n\
- light_factor -= texture(" + std::string(shadowSampler) + ", vec4(shadow_coord.xy + vec2(u, v) * offs, index, shadow_coord.z)) * blur_weights[((v + " + rad + ") * " + rad + ") + u + " + rad + "];\n\
- }\n\
- }\n";
- }
- else {
- shader_src += std::string(" float light_factor = 1.f - ") + (gs.shadowsPCF() ? "texture(" + std::string(shadowSampler) + ", vec4(shadow_coord.xy, index, shadow_coord.z))" : "float(shadow_coord.z > texture(" + std::string(shadowSampler) + ", vec3(shadow_coord.xy, index)).r)") + ";\n";
- }
- shader_src += " specular *= light_factor;\n\
- diffuse *= light_factor;\n";
- if (!gs.shadowsPCF()) {
- shader_src += " }\n";
- }
- }
- shader_src += " fragmentColor = " + std::string(lightIntensity) + " * albedo * (" + std::string(ambientConstant) + " + " + std::string(diffuseConstant) + " * diffuse + " + std::string(specularConstant) + " * specular);\n";
- if (gs.screenSpaceReflections()) {
- if (flags & MR_REFLECTIVE) {
- shader_src += " mat3 mv_inverse = " + std::string(viewMatrixOrtho) + " * " + std::string(modelMatrixTransposeInverse) + ";\n";
- if (tangent_space) {
- shader_src += " mat3 tangent_to_view = mat3(normalize(mv_inverse * tangent_local.xyz), normalize(mv_inverse * bitangent_local), normalize(mv_inverse * normal_local));\n\
- viewSpaceNormal = normalize(tangent_to_view * n);\n";
- }
- else {
- shader_src += " viewSpaceNormal = normalize(mv_inverse * normal_local);\n";
- }
- }
- else {
- shader_src += " viewSpaceNormal = vec3(0.f);\n";
- }
- }
- shader_src += "}\n";
- return shader_src;
- }
- std::string GLSLShaderGenerator::createMeshFragmentDepthSource(unsigned const & flags, GraphicsSettings const & gs) const
- {
- std::string shader_src = "#version 330\n\
- in vec2 uv_out;\n";
- if (flags & MR_ALPHA_MAP) {
- shader_src += "uniform sampler2D " + std::string(alphaSampler) + ";\n";
- }
- shader_src += "void main()\n\
- {\n";
- if (flags & MR_ALPHA_MAP) {
- shader_src += " if (texture(" + std::string(alphaSampler) + ", uv_out).r < 0.5f){\n\
- discard;\n\
- }\n";
- }
- shader_src += "}";
- return shader_src;
- }
- std::string GLSLShaderGenerator::createCompositeShaderSource(GraphicsSettings const & gs, bool const & god_rays) const
- {
- std::string shader_src = "#version 330\n\
- layout(location = 0) out vec3 fragmentColor;\n\
- uniform sampler2D " + std::string(lightingSampler) + ";\n\
- uniform sampler2D " + std::string(depthSampler) + ";\n\
- uniform sampler2D " + std::string(dofSampler) + ";\n\
- uniform sampler2D " + std::string(godRaySampler) + ";\n\
- uniform sampler2D " + std::string(bloomSampler) + ";\n\
- uniform vec4 " + std::string(projectionMatrixInverseThirdRow) + ";\n\
- uniform vec4 " + std::string(projectionMatrixInverseFourthRow) + ";\n\
- uniform vec3 " + godRayIntensity + ";\n\
- uniform float " + std::string(maxMipLevel) + ";\n\
- in vec2 uv;\n\
- void main()\n\
- {\n\
- fragmentColor = textureLod(" + std::string(lightingSampler) + ", uv, 0.f).rgb;\n";
- if (gs.depthOfField()) {
- shader_src += " vec4 pos_ndc = vec4(vec3(uv, texture(" + std::string(depthSampler) + ", uv).r) * 2.f - 1.f, 1.f);\n\
- float depth_view = dot(" + std::string(projectionMatrixInverseThirdRow) + ", pos_ndc) / dot(" + std::string(projectionMatrixInverseFourthRow) + ", pos_ndc);\n\
- vec3 blur_color = texture(" + std::string(dofSampler) + ", uv).rgb;\n\
- if (depth_view >= " + str(gs.dofCenter()) + "){\n\
- fragmentColor = mix(fragmentColor, blur_color, smoothstep(" + str(gs.dofCenter()) + ", " + str(gs.dofFar()) + ", depth_view));\n\
- }\n\
- else {\n\
- fragmentColor = mix(blur_color, fragmentColor, smoothstep(" + str(gs.dofNear()) + ", " + str(gs.dofCenter()) + ", depth_view));\n\
- }\n";
- }
- if (gs.autoExposure()) {
- shader_src += " float scene_brightness = dot(textureLod(" + std::string(lightingSampler) + ", vec2(0.5f), " + std::string(maxMipLevel) + ").rgb , vec3(0.2126f, 0.7152f, 0.0722f));\n";
- }
- if (god_rays) {
- shader_src += " fragmentColor += texture(" + std::string(godRaySampler) + ", uv).rgb * " + godRayIntensity + ";\n";
- }
- if (gs.bloom()) {
- shader_src += " fragmentColor += texture(" + std::string(bloomSampler) + ", uv).rgb" + (gs.autoExposure() ? " * (1.f - smoothstep(0.f, " + str(gs.refBrightness()) + ", scene_brightness))" : "") + ";\n";
- }
- if (gs.exposureEnabled()) {
- shader_src += " fragmentColor *= " + str(gs.exposure()) + (gs.autoExposure() ? " * clamp(0.25f / scene_brightness, 0.5f, 3.f)" : "") + ";\n";
- }
- shader_src += " fragmentColor /= 1.f + fragmentColor;\n";
- if (gs.gammaEnabled()) {
- shader_src += " fragmentColor = pow(fragmentColor, vec3(" + str(1.f / gs.gamma()) + "));\n";
- }
- return shader_src + "}\n";
- }
- std::string GLSLShaderGenerator::blurSource(StackTrivial<float> const & weights) const
- {
- std::string res = " const float blur_weights[" + str(weights.size()) + "] = float[](";
- for (auto* ptr = weights.begin(); ptr != weights.end(); ptr++) {
- res += str(*ptr);
- res += ptr == weights.end() - 1u ? ");\n" : ",";
- }
- return res;
- }
- }
- #include <physics/PhysicsCameraController.h>
- #include <GameTimer.h>
- #include <Camera.h>
- #include <iostream>
- #include <BoundingVolumeHierarchy.h>
- #include <Triangle.h>
- #include <set>
- namespace Log2
- {
- PhysicsCameraController::PhysicsCameraController(Camera* const & camera, BoundingVolumeHierarchy*& bvh) :
- _c(camera),
- _bvh(bvh)
- {
- }
- void PhysicsCameraController::updateSystem()
- {
- setDamping(DAMP_DEFAULT);
- auto const v_new = _velocity + ((_acceleration + _gravity) * _dt);
- auto const v_constant = v_new * _dt;
- auto p2 = _c->pos() + v_constant;
- if (_collisions) {
- auto v_inv = Vector(static_cast<Type>(1)) / v_constant;
- auto min_t_first = std::numeric_limits<Type>::max();
- Primitive const * nearest = nullptr;
- _bvh->intersectNested(_c->collisionShape(), v_constant, v_inv, min_t_first, [this, &min_t_first, &nearest, &v_constant, &v_inv](Primitive const * imr) {
- boost::object_pool<Triangle> tri_pool;
- StackTrivial<Vertex> vertices;
- imr->getTransformedBVH(tri_pool, vertices)->intersectPrimitives(_c->collisionShape(), v_constant, v_inv, min_t_first, nearest);
- setDamping(DAMP_INTERIOR);
- });
- _c->setPosition(nearest ? lerp(_c->pos(), p2, min_t_first) : p2);
- }
- else {
- _c->setPosition(p2);
- }
- _velocity = v_new * _damp;
- _angularVelocity += _angularAcceleration * _dt;
- _c->setEulerRadians(_c->eulerRadians() - _angularVelocity * _dt);
- _angularVelocity *= DAMP_DEFAULT;
- }
- unsigned PhysicsCameraController::getID()
- {
- return 0;
- }
- const char * PhysicsCameraController::getName()
- {
- return "PhysicsCameraController";
- }
- void PhysicsCameraController::setAcceleration(Vector const & dir, Type const & amount)
- {
- _acceleration = dir.length() > static_cast<Type>(0) ? normalize(dir) * amount : static_cast<Type>(0);
- }
- void PhysicsCameraController::setAngularAcceleration(Vector const & aa)
- {
- _angularAcceleration = aa;
- }
- Camera* const & PhysicsCameraController::getCamera() const
- {
- return _c;
- }
- void PhysicsCameraController::setCamera(Camera* const & camera)
- {
- _c = camera;
- }
- void PhysicsCameraController::setDamping(Type const & damping)
- {
- _damp = damping;
- }
- PhysicsCameraController::Vector const & PhysicsCameraController::gravity() const
- {
- return _gravity;
- }
- void PhysicsCameraController::setGravity(Vector const & gravity)
- {
- _gravity = gravity;
- }
- bool const & PhysicsCameraController::collisions() const
- {
- return _collisions;
- }
- void PhysicsCameraController::setCollisions(bool const & collisions)
- {
- _collisions = collisions;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement