光線と平面の交点を求める

plane-ray-intersection.png
ガチでテストする前にまずは可能性について考えなくてはなりません
plane-ray-intersection.png
平面の法線とレイの方向ベクトルのなす角が直角だったら、no intersectionline contained planeになりそうですね。
なので内積を調べて0になったら、return false;です。
template<typename T>
bool rayPlaneIntersect(Ray& _ray,Plane& _plane,vec3<T>* _result){
   if( _ray.mDir.innerProduct(_plane.mNormal)==0){
             return false;//レイと平面は平行であるので交わらない
}
}

平面の方程式はこうです(1)
\begin{equation} n_{x}x+n_yy+n_zz+d=0 \end{equation}

そして、光線の方程式はこうです

(2)
\begin{equation} tV_{dir}+P_n=(x,y,z) \end{equation}

Vは光線の方向を指しています。長さ1に正規化されたベクトルです。
tは媒介変数です。求めたいのはこのtになりますね。
Pは光線の始まる始点となる位置です。
この媒介変数tさえわかってしまえば交点がわかります。
tを求めるには、、、まず光線の式をもっとわかりやすく、ベクトル表記にします

(3)
\begin{align} t \begin{pmatrix} V_x\\ V_y\\ V_Z \end{pmatrix} + \begin{pmatrix} P_x\\ P_y\\ P_z \end{pmatrix} = \begin{pmatrix} x\\ y\\ z \end{pmatrix} \end{align}

知りたい交点(x,y,z)はこう表記できます

(4)
\begin{pmatrix} tV_x+P_x\\ tV_y+P_y\\ tV_z+P_z \end{pmatrix}

これを平面の方程式の方にあてはめると、こうなる

(5)
\begin{equation} n_x(tV_x+P_x)+n_x(tV_y+P_y)+n_z(tV_z+P_z)+d=0 \end{equation}

これを、うまいことt=になるように式を変形します

(6)
\begin{align} n_xtV_x+P_xn_x+n_ytV_y+n_yP_y+n_ztV_z+n_zP_z+d=0\\ t(n_xV_x+n_yV_y+n_zV_z)+P_xn_x+P_yn_y+P_zn_z+d=0\\ t=\frac{-(P_xn_x+P_yn_y+P_zn_z+d)}{n_xV_x+n_yV_y+n_zV_z} \end{align}

まとめると

(7)
\begin{align} t=\frac{n \cdot P}{n \cdot V}\\ t=\frac{法線 ・平面上の点}{法線・光線の方向ベクトル} \end{align}

ソースコード

#ifndef MIFFY_INTERSECT
 
#define MIFFY_INTERSECT
 
namespace miffy{
  template <typename T>
  static bool rayPlaneIntersect(const vec3<T>& _rayDir,const vec3<T>& _rayBegin,const vec3<T>& _planeNormal,const T _planeDist,vec3<T>* _intersect){
    T denom=_rayDir.innerProduct(_planeNormal);
    if(denom==0){//交差していない。 平行状態である
      return false;
    }
    //媒介変数=t
    T t=-(_planeNormal.innerProduct(_rayBegin))/denom;
    _intersect->set(_rayBegin+_rayDir*t);
    return true;
  }
};
#endif

git
レイと平面の交差テストプログラム(git)

intersection plane ray-intersection unproject

サポートサイト Wikidot.com intersectionplaneray-intersectionunproject