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