Path: blob/master/thirdparty/embree/common/math/bbox.h
9912 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "vec2.h"6#include "vec3.h"78namespace embree9{10namespace internal {1112template <typename T> __forceinline T divideByTwo(const T& v) { return v / T(2); }13template <> __forceinline float divideByTwo<float>(const float& v) { return v * 0.5f; }14template <> __forceinline double divideByTwo<double>(const double& v) { return v * 0.5; }1516} // namespace internal17template<typename T>18struct BBox19{20T lower, upper;2122////////////////////////////////////////////////////////////////////////////////23/// Construction24////////////////////////////////////////////////////////////////////////////////2526__forceinline BBox ( ) { }27template<typename T1>28__forceinline BBox ( const BBox<T1>& other ) : lower(other.lower), upper(other.upper) {}29__forceinline BBox& operator=( const BBox& other ) { lower = other.lower; upper = other.upper; return *this; }3031__forceinline BBox ( const T& v ) : lower(v), upper(v) {}32__forceinline BBox ( const T& lower, const T& upper ) : lower(lower), upper(upper) {}3334////////////////////////////////////////////////////////////////////////////////35/// Extending Bounds36////////////////////////////////////////////////////////////////////////////////3738__forceinline const BBox& extend(const BBox& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }39__forceinline const BBox& extend(const T & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }4041/*! tests if box is empty */42__forceinline bool empty() const { for (int i=0; i<T::N; i++) if (lower[i] > upper[i]) return true; return false; }4344/*! computes the size of the box */45__forceinline T size() const { return upper - lower; }4647/*! computes the center of the box */48__forceinline T center() const { return internal::divideByTwo<T>(lower+upper); }4950/*! computes twice the center of the box */51__forceinline T center2() const { return lower+upper; }5253/*! merges two boxes */54__forceinline static const BBox merge (const BBox& a, const BBox& b) {55return BBox(min(a.lower, b.lower), max(a.upper, b.upper));56}5758/*! intersects two boxes */59__forceinline static const BBox intersect (const BBox& a, const BBox& b) {60return BBox(max(a.lower, b.lower), min(a.upper, b.upper));61}6263/*! enlarge box by some scaling factor */64__forceinline BBox enlarge_by(const float a) const {65return BBox(lower - T(a)*abs(lower), upper + T(a)*abs(upper));66}6768////////////////////////////////////////////////////////////////////////////////69/// Constants70////////////////////////////////////////////////////////////////////////////////7172__forceinline BBox( EmptyTy ) : lower(pos_inf), upper(neg_inf) {}73__forceinline BBox( FullTy ) : lower(neg_inf), upper(pos_inf) {}74__forceinline BBox( FalseTy ) : lower(pos_inf), upper(neg_inf) {}75__forceinline BBox( TrueTy ) : lower(neg_inf), upper(pos_inf) {}76__forceinline BBox( NegInfTy ): lower(pos_inf), upper(neg_inf) {}77__forceinline BBox( PosInfTy ): lower(neg_inf), upper(pos_inf) {}78};7980template<> __forceinline bool BBox<float>::empty() const {81return lower > upper;82}8384#if defined(__SSE__) || defined(__ARM_NEON)85template<> __forceinline bool BBox<Vec3fa>::empty() const {86return !all(le_mask(lower,upper));87}88template<> __forceinline bool BBox<Vec3fx>::empty() const {89return !all(le_mask(lower,upper));90}91#endif9293/*! tests if box is finite */94__forceinline bool isvalid( const BBox<Vec3fa>& v ) {95return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)));96}9798/*! tests if box is finite and non-empty*/99__forceinline bool isvalid_non_empty( const BBox<Vec3fa>& v ) {100return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)) & le_mask(v.lower,v.upper));101}102103/*! tests if box has finite entries */104__forceinline bool is_finite( const BBox<Vec3fa>& b) {105return is_finite(b.lower) && is_finite(b.upper);106}107108/*! test if point contained in box */109__forceinline bool inside ( const BBox<Vec3fa>& b, const Vec3fa& p ) { return all(ge_mask(p,b.lower) & le_mask(p,b.upper)); }110111/*! computes the center of the box */112template<typename T> __forceinline const T center2(const BBox<T>& box) { return box.lower + box.upper; }113template<typename T> __forceinline const T center (const BBox<T>& box) { return internal::divideByTwo<T>(center2(box)); }114115/*! computes the volume of a bounding box */116__forceinline float volume ( const BBox<Vec3fa>& b ) { return reduce_mul(b.size()); }117__forceinline float safeVolume( const BBox<Vec3fa>& b ) { if (b.empty()) return 0.0f; else return volume(b); }118119/*! computes the volume of a bounding box */120__forceinline float volume( const BBox<Vec3f>& b ) { return reduce_mul(b.size()); }121122/*! computes the surface area of a bounding box */123template<typename T> __forceinline const T area( const BBox<Vec2<T> >& b ) { const Vec2<T> d = b.size(); return d.x*d.y; }124125template<typename T> __forceinline const T halfArea( const BBox<Vec3<T> >& b ) { return halfArea(b.size()); }126template<typename T> __forceinline const T area( const BBox<Vec3<T> >& b ) { return T(2)*halfArea(b); }127128__forceinline float halfArea( const BBox<Vec3fa>& b ) { return halfArea(b.size()); }129__forceinline float area( const BBox<Vec3fa>& b ) { return 2.0f*halfArea(b); }130131__forceinline float halfArea( const BBox<Vec3fx>& b ) { return halfArea(b.size()); }132__forceinline float area( const BBox<Vec3fx>& b ) { return 2.0f*halfArea(b); }133134template<typename Vec> __forceinline float safeArea( const BBox<Vec>& b ) { if (b.empty()) return 0.0f; else return area(b); }135136template<typename T> __forceinline float expectedApproxHalfArea(const BBox<T>& box) {137return halfArea(box);138}139140/*! merges bounding boxes and points */141template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const T& b ) { return BBox<T>(min(a.lower, b ), max(a.upper, b )); }142template<typename T> __forceinline const BBox<T> merge( const T& a, const BBox<T>& b ) { return BBox<T>(min(a , b.lower), max(a , b.upper)); }143template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(min(a.lower, b.lower), max(a.upper, b.upper)); }144145/*! Merges three boxes. */146template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return merge(a,merge(b,c)); }147148/*! Merges four boxes. */149template<typename T> __forceinline BBox<T> merge(const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d) {150return merge(merge(a,b),merge(c,d));151}152153/*! Comparison Operators */154template<typename T> __forceinline bool operator==( const BBox<T>& a, const BBox<T>& b ) { return a.lower == b.lower && a.upper == b.upper; }155template<typename T> __forceinline bool operator!=( const BBox<T>& a, const BBox<T>& b ) { return a.lower != b.lower || a.upper != b.upper; }156157/*! scaling */158template<typename T> __forceinline BBox<T> operator *( const float& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }159template<typename T> __forceinline BBox<T> operator *( const T& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }160161/*! translations */162template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower+b.lower,a.upper+b.upper); }163template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower-b.lower,a.upper-b.upper); }164template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower+b ,a.upper+b ); }165template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower-b ,a.upper-b ); }166167/*! extension */168template<typename T> __forceinline BBox<T> enlarge(const BBox<T>& a, const T& b) { return BBox<T>(a.lower-b, a.upper+b); }169170/*! intersect bounding boxes */171template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(max(a.lower, b.lower), min(a.upper, b.upper)); }172template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return intersect(a,intersect(b,c)); }173template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d ) { return intersect(intersect(a,b),intersect(c,d)); }174175/*! subtract bounds from each other */176template<typename T> __forceinline void subtract(const BBox<T>& a, const BBox<T>& b, BBox<T>& c, BBox<T>& d)177{178c.lower = a.lower;179c.upper = min(a.upper,b.lower);180d.lower = max(a.lower,b.upper);181d.upper = a.upper;182}183184/*! tests if bounding boxes (and points) are disjoint (empty intersection) */185template<typename T> __inline bool disjoint( const BBox<T>& a, const BBox<T>& b ) { return intersect(a,b).empty(); }186template<typename T> __inline bool disjoint( const BBox<T>& a, const T& b ) { return disjoint(a,BBox<T>(b)); }187template<typename T> __inline bool disjoint( const T& a, const BBox<T>& b ) { return disjoint(BBox<T>(a),b); }188189/*! tests if bounding boxes (and points) are conjoint (non-empty intersection) */190template<typename T> __inline bool conjoint( const BBox<T>& a, const BBox<T>& b ) { return !intersect(a,b).empty(); }191template<typename T> __inline bool conjoint( const BBox<T>& a, const T& b ) { return conjoint(a,BBox<T>(b)); }192template<typename T> __inline bool conjoint( const T& a, const BBox<T>& b ) { return conjoint(BBox<T>(a),b); }193194/*! subset relation */195template<typename T> __inline bool subset( const BBox<T>& a, const BBox<T>& b )196{197for ( size_t i = 0; i < T::N; i++ ) if ( a.lower[i] < b.lower[i] ) return false;198for ( size_t i = 0; i < T::N; i++ ) if ( a.upper[i] > b.upper[i] ) return false;199return true;200}201202template<> __inline bool subset( const BBox<Vec3fa>& a, const BBox<Vec3fa>& b ) {203return all(ge_mask(a.lower,b.lower)) && all(le_mask(a.upper,b.upper));204}205206template<> __inline bool subset( const BBox<Vec3fx>& a, const BBox<Vec3fx>& b ) {207return all(ge_mask(a.lower,b.lower)) && all(le_mask(a.upper,b.upper));208}209210/*! blending */211template<typename T>212__forceinline BBox<T> lerp(const BBox<T>& b0, const BBox<T>& b1, const float t) {213return BBox<T>(lerp(b0.lower,b1.lower,t),lerp(b0.upper,b1.upper,t));214}215216/*! output operator */217template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const BBox<T>& box) {218return cout << "[" << box.lower << "; " << box.upper << "]";219}220221/*! default template instantiations */222typedef BBox<float> BBox1f;223typedef BBox<Vec2f> BBox2f;224typedef BBox<Vec2fa> BBox2fa;225typedef BBox<Vec3f> BBox3f;226typedef BBox<Vec3fa> BBox3fa;227typedef BBox<Vec3fx> BBox3fx;228typedef BBox<Vec3ff> BBox3ff;229}230231////////////////////////////////////////////////////////////////////////////////232/// SSE / AVX / MIC specializations233////////////////////////////////////////////////////////////////////////////////234235#if defined (__SSE__) || defined(__ARM_NEON)236#include "../simd/sse.h"237#endif238239#if defined (__AVX__)240#include "../simd/avx.h"241#endif242243#if defined(__AVX512F__)244#include "../simd/avx512.h"245#endif246247namespace embree248{249template<int N>250__forceinline BBox<Vec3<vfloat<N>>> transpose(const BBox3fa* bounds);251252template<>253__forceinline BBox<Vec3<vfloat4>> transpose<4>(const BBox3fa* bounds)254{255BBox<Vec3<vfloat4>> dest;256257transpose((vfloat4&)bounds[0].lower,258(vfloat4&)bounds[1].lower,259(vfloat4&)bounds[2].lower,260(vfloat4&)bounds[3].lower,261dest.lower.x,262dest.lower.y,263dest.lower.z);264265transpose((vfloat4&)bounds[0].upper,266(vfloat4&)bounds[1].upper,267(vfloat4&)bounds[2].upper,268(vfloat4&)bounds[3].upper,269dest.upper.x,270dest.upper.y,271dest.upper.z);272273return dest;274}275276#if defined(__AVX__)277template<>278__forceinline BBox<Vec3<vfloat8>> transpose<8>(const BBox3fa* bounds)279{280BBox<Vec3<vfloat8>> dest;281282transpose((vfloat4&)bounds[0].lower,283(vfloat4&)bounds[1].lower,284(vfloat4&)bounds[2].lower,285(vfloat4&)bounds[3].lower,286(vfloat4&)bounds[4].lower,287(vfloat4&)bounds[5].lower,288(vfloat4&)bounds[6].lower,289(vfloat4&)bounds[7].lower,290dest.lower.x,291dest.lower.y,292dest.lower.z);293294transpose((vfloat4&)bounds[0].upper,295(vfloat4&)bounds[1].upper,296(vfloat4&)bounds[2].upper,297(vfloat4&)bounds[3].upper,298(vfloat4&)bounds[4].upper,299(vfloat4&)bounds[5].upper,300(vfloat4&)bounds[6].upper,301(vfloat4&)bounds[7].upper,302dest.upper.x,303dest.upper.y,304dest.upper.z);305306return dest;307}308#endif309310template<int N>311__forceinline BBox3fa merge(const BBox3fa* bounds);312313template<>314__forceinline BBox3fa merge<4>(const BBox3fa* bounds)315{316const Vec3fa lower = min(min(bounds[0].lower,bounds[1].lower),317min(bounds[2].lower,bounds[3].lower));318const Vec3fa upper = max(max(bounds[0].upper,bounds[1].upper),319max(bounds[2].upper,bounds[3].upper));320return BBox3fa(lower,upper);321}322323#if defined(__AVX__)324template<>325__forceinline BBox3fa merge<8>(const BBox3fa* bounds)326{327const Vec3fa lower = min(min(min(bounds[0].lower,bounds[1].lower),min(bounds[2].lower,bounds[3].lower)),328min(min(bounds[4].lower,bounds[5].lower),min(bounds[6].lower,bounds[7].lower)));329const Vec3fa upper = max(max(max(bounds[0].upper,bounds[1].upper),max(bounds[2].upper,bounds[3].upper)),330max(max(bounds[4].upper,bounds[5].upper),max(bounds[6].upper,bounds[7].upper)));331return BBox3fa(lower,upper);332}333#endif334}335336337338