isectBox
https://gyazo.com/0e2225fdf0534fc9f762ac08e2e8c31e
半直線と箱の交差判定
GLSL
xyzに法線、wに距離
code:glsl
vec4 isectBox( vec3 ro, vec3 rd, vec3 s ) {
vec3 xo = -ro / rd; // 次元ごとに、rd・Nを加味したroの原点までの距離
vec3 xs = abs( s / rd ); // 次元ごとに、rd・Nを加味した板の原点までの距離
vec3 dfv = xo - xs; // 次元ごとに、手前・表面の方の板までの距離
vec3 dbv = xo + xs; // 次元ごとに、奥・裏面の方の板までの距離
float df = max( dfv.x, max( dfv.y, dfv.z ) ); // 一番遠い表面までの距離
float db = min( dbv.x, min( dbv.y, dbv.z ) ); // 一番近い裏面までの距離
if ( df < 0.0 ) { return vec4( FAR ); } // 表面が背後にある場合
if ( db < df ) { return vec4( FAR ); } // 裏面が表面より先に見えた場合
vec3 n = -sign( rd ) * step( vec3( df ), dfv ); // rdの向きどーっちどっち * 衝突した面はどの次元じゃろな
return vec4( n, df ); // xyzに法線、wに距離
}
Desmos
二次元ですが
https://gyazo.com/86a6a4b80c09bf29e63b8d7aa9d4d2f8
考え方
loとls
次元ごとに距離を求める
ベクトルというより配列と意識?
roの位置・板の位置を、それぞれrd・Nを考慮して求める、と意識
rdとNは向き合うとき正なので符号は負
fとb・flとbl
まず直方体の内外判定を意識
一旦二次元で考えても良き
達成しなきゃいけない条件は6つ、各次元ごとにmin < x・x < max
解釈し直すと、直方体を構成する6枚の無限平面の内側
更に解釈し直すと、直方体を構成する6枚の無限平面のうち、手前の3枚より奥の部分かつ、奥の3枚より手前の部分
「手前の3枚より奥」は「手前の3枚のうち一番奥の面より奥」と解釈し直せる
「奥の3枚より手前」は「奥の3枚のうち一番手前の面より手前」と解釈し直せる
n
step( vec3( df ), dfv ) は、「交差した面の次元が1・それ以外が0の vec3 」という意味
step 関数は、 a <= b ? 1 : 0 。イコールが重要
iqの原典だと step( fv.yzx, fv ) * step( fv.zxy, fv ) 結局やりたいことは同じ
iqに内側もヒットする版を作ってもらった:
step( dbv, vec3( db ) ) で内側の法線が取れる
-sign( rd ) は、「rdとNは向き合っている」で覚える
References