MeshLib C++ Docs
Loading...
Searching...
No Matches
MRRayBoxIntersection.h
Go to the documentation of this file.
1#pragma once
2#include "MRBox.h"
4#include "MRMesh/MRMacros.h"
5#include "MRPch/MRBindingMacros.h"
6#include <cassert>
7
8namespace MR
9{
10
14
15template<typename T>
17{
20 RayOrigin( const Vector3<T> & ro ) : p( ro ) { }
21};
22
24#if defined(__x86_64__) || defined(_M_X64)
25template<>
26struct RayOrigin<float>
27{
28 MR_BIND_IGNORE __m128 p;
29 RayOrigin( const Vector3f & ro ) { p = _mm_set_ps( 0, ro.z, ro.y, ro.x ); }
30};
31
33#elif defined(__aarch64__) || defined(_M_ARM64)
34template<>
35struct RayOrigin<float>
36{
37 MR_BIND_IGNORE float32x4_t p;
38 RayOrigin( const Vector3f & ro ) { p = toFloat32x4( ro.x, ro.y, ro.z, 0 ); }
39};
40
42#elif defined(__wasm_simd128__)
43template<>
44struct RayOrigin<float>
45{
46 MR_BIND_IGNORE v128_t p;
47 RayOrigin( const Vector3f & ro ) { p = wasm_f32x4_make( ro.x, ro.y, ro.z, 0 ); }
48};
49#endif
50
55template <typename T = float>
56bool rayBoxIntersect( const Box3<T>& box, const RayOrigin<T> & rayOrigin, T & t0, T & t1, const IntersectionPrecomputes<T>& prec )
57{
58 assert( box.valid() );
59
60 #if defined(__x86_64__) || defined(_M_X64)
61 if constexpr (std::is_same_v<T, float>)
62 {
64 static_assert( sizeof( Box3f ) == 6 * sizeof( float ) );
65 const float * const c = &box.min.x;
66 __m128 l = _mm_loadu_ps( c );
67 __m128 h = _mm_loadu_ps( c + 2 );
68 __m128 r = _mm_shuffle_ps( h, h, _MM_SHUFFLE( 3, 3, 2, 1 ) );
69
70 l = _mm_mul_ps( _mm_sub_ps( l, rayOrigin.p ), prec.invDir );
71 r = _mm_mul_ps( _mm_sub_ps( r, rayOrigin.p ), prec.invDir );
72
73 __m128 a = _mm_min_ps( l, r );
74 __m128 b = _mm_max_ps( l, r );
75
77 __m128 az = _mm_shuffle_ps( a, a, _MM_SHUFFLE( 2, 2, 2, 2 ) );
78 __m128 ay = _mm_shuffle_ps( a, a, _MM_SHUFFLE( 1, 1, 1, 1 ) );
79 t0 = _mm_cvtss_f32( _mm_max_ss( _mm_max_ss( _mm_max_ss( a, az ), ay ), _mm_load_ss( &t0 ) ) );
80
81 __m128 bz = _mm_shuffle_ps( b, b, _MM_SHUFFLE( 2, 2, 2, 2 ) );
82 __m128 by = _mm_shuffle_ps( b, b, _MM_SHUFFLE( 1, 1, 1, 1 ) );
83 t1 = _mm_cvtss_f32( _mm_min_ss( _mm_min_ss( _mm_min_ss( b, bz ), by ), _mm_load_ss( &t1 ) ) );
84
85 return t0 <= t1;
86 }
87 else
88 #elif defined(__aarch64__) || defined(_M_ARM64)
89 if constexpr (std::is_same_v<T, float>)
90 {
93 static_assert( sizeof( Box3f ) == 6 * sizeof( float ) );
94 const float * const c = &box.min.x;
95 float32x4_t h = vld1q_f32( c + 2 );
96 float32x4_t l = vsetq_lane_f32( t0, vld1q_f32( c ), 3 );
97 float32x4_t r = vsetq_lane_f32( t1, vextq_f32( h, h, 1 ), 3 );
98
99 l = vmulq_f32( vsubq_f32( l, rayOrigin.p ), prec.invDir );
100 r = vmulq_f32( vsubq_f32( r, rayOrigin.p ), prec.invDir );
101
102 t0 = vmaxvq_f32( vminq_f32( l, r ) );
103 t1 = vminvq_f32( vmaxq_f32( l, r ) );
104
105 return t0 <= t1;
106 }
107 else
108 #elif defined(__wasm_simd128__)
109 if constexpr (std::is_same_v<T, float>)
110 {
112 static_assert( sizeof( Box3f ) == 6 * sizeof( float ) );
113 const float * const c = &box.min.x;
114 v128_t l = wasm_v128_load( c );
115 v128_t h = wasm_v128_load( c + 2 );
116 v128_t r = wasm_i32x4_shuffle( h, h, 1, 2, 3, 3 );
117
118 l = wasm_f32x4_mul( wasm_f32x4_sub( l, rayOrigin.p ), prec.invDir );
119 r = wasm_f32x4_mul( wasm_f32x4_sub( r, rayOrigin.p ), prec.invDir );
120
121 v128_t a = wasm_f32x4_pmin( l, r );
122 v128_t b = wasm_f32x4_pmax( l, r );
123
126 v128_t az = wasm_i32x4_shuffle( a, a, 2, 2, 2, 2 );
127 v128_t ay = wasm_i32x4_shuffle( a, a, 1, 1, 1, 1 );
128 v128_t bz = wasm_i32x4_shuffle( b, b, 2, 2, 2, 2 );
129 v128_t by = wasm_i32x4_shuffle( b, b, 1, 1, 1, 1 );
130
131 t0 = std::max( t0, wasm_f32x4_extract_lane( wasm_f32x4_pmax( wasm_f32x4_pmax( a, az ), ay ), 0 ) );
132 t1 = std::min( t1, wasm_f32x4_extract_lane( wasm_f32x4_pmin( wasm_f32x4_pmin( b, bz ), by ), 0 ) );
133
134 return t0 <= t1;
135 }
136 else
137 #else
138 #pragma message("rayBoxIntersect: no hardware optimized instructions")
139 #endif
140 {
141 const Vector3i& sign = prec.sign;
142
144 t1 = std::min( (box[sign.x].x - rayOrigin.p.x) * prec.invDir.x, t1 );
145 t0 = std::max( (box[1 - sign.x].x - rayOrigin.p.x) * prec.invDir.x, t0 );
146
148 t1 = std::min( (box[sign.y].y - rayOrigin.p.y) * prec.invDir.y, t1 );
149 t0 = std::max( (box[1 - sign.y].y - rayOrigin.p.y) * prec.invDir.y, t0 );
150
152 t1 = std::min( (box[sign.z].z - rayOrigin.p.z) * prec.invDir.z, t1 );
153 t0 = std::max( (box[1 - sign.z].z - rayOrigin.p.z) * prec.invDir.z, t0 );
154 return t0 <= t1;
155 }
156}
157
159template <typename T = float>
160bool rayBoxIntersect( const Box3<T>& box, const Line3<T>& line, T t0, T t1 )
161{
162 IntersectionPrecomputes<T> prec( line.d );
163 return rayBoxIntersect( box, RayOrigin<T>( line.p ), t0, t1, prec );
164}
165
167
168}
Box< Vector3< T > > Box3
Definition MRMeshFwd.h:422
Line< Vector3< T > > Line3
Definition MRMeshFwd.h:340
std::array< Vector3f, 3 > MR_BIND_IGNORE
Definition MRMeshBuilderTypes.h:13
bool rayBoxIntersect(const Box3< T > &box, const RayOrigin< T > &rayOrigin, T &t0, T &t1, const IntersectionPrecomputes< T > &prec)
Definition MRRayBoxIntersection.h:56
only for bindings generation
Definition MRCameraOrientationPlugin.h:8
V min
Definition MRBox.h:35
bool valid() const
true if the box contains at least one point
Definition MRBox.h:66
Definition MRIntersectionPrecomputes.h:121
MR_BIND_IGNORE Vector3i sign
stores signs of direction vector;
Definition MRIntersectionPrecomputes.h:131
MR_BIND_IGNORE Vector3< T > invDir
{1 / dir}
Definition MRIntersectionPrecomputes.h:123
Definition MRRayBoxIntersection.h:17
RayOrigin(const Vector3< T > &ro)
Definition MRRayBoxIntersection.h:20
MR_BIND_IGNORE Vector3< T > p
This is hidden to match the specialization below.
Definition MRRayBoxIntersection.h:19
Definition MRVector3.h:33