こんにちわ。
どの辺りが分かっていないの分からず、あてずっぽうになってしまい申し訳ないですが。
おそらく。。。ここが理解できてない可能性がある所に★コメントしました。
宜しかったらどうぞ。
1)面の法線と線分の開始、終了点の内積をとれば裏表は分かる。
表表:貫通してない ×
裏裏:貫通してない ×
表裏:貫通している ○
2)面(板ポリゴン)の接触した点が含まれるかは法線が一致しているか見ればわかる。
面の法線が↑の時、各辺と接触した点の法線が、、、
↑↑↑:含まれる ○
↑↑↓:含まれない ×
↑↓↑:含まれない ×
etc...
3)接触位置は2)を求める段階で既に分かってますのでそのまま使えば良いです。
; 基本的なベクトル演算
#module
#deffunc vadd array res, array a, array b ; 加算
res = a.0 + b.0, a.1 + b.1, a.2 + b.2 : return
#deffunc vsub array res, array a, array b ; 減算
res = a.0 - b.0, a.1 - b.1, a.2 - b.2 : return
#deffunc vmul array res, array a, array b ; 乗算
res = a.0 * b.0, a.1 * b.1, a.2 * b.2 : return
#deffunc vdiv array res, array a, array b ; 除算
res = a.0 / b.0, a.1 / b.1, a.2 / b.2 : return
#deffunc vunit array res ; 単位ベクトル
_d = sqrt(res.0*res.0 + res.1*res.1 + res.2*res.2)+0.00000000001
res = res.0/_d, res.1 / _d, res.2 / _d : return
#defcfunc dot array a, array b ; 内積
return a.0 * b.0 + a.1 * b.1 + a.2 * b.2
#deffunc cross array res, array a, array b ; 外積
res = a.1*b.2-a.2*b.1, a.2*b.0-a.0*b.2, a.0*b.1-a.1*b.0 : return
#deffunc normal array res, array f ; 面の法線
_a = f.3-f.0, f.4-f.1, f.5-f.2 : _b = f.6-f.0, f.7-f.1, f.8-f.2 : cross res, _a, _b : return
#deffunc fmid array res, array f ; 面の中心
res = (f.0+f.3+f.6)/3,(f.1+f.4+f.7)/3,(f.2+f.5+f.8)/3 : return
#global
#include "d3m.hsp"
; 初期設定
; ---------------------------------------------------------------
screen 0, 800, 800
repeat 4, 1 : buffer cnt, 400,400 : loop : gsel 0
speed = 0.05
; 線分
sp = 2.0, 2.0, 2.0 ; 開始
ep = 2.0, 2.0, -2.0 ; 終了
; 面
f.0 = 0.0, 5.0, 0.; 点1
f.3 = 4.3, -2.5, 0.; 点2
f.6 = -4.3, -2.5, 0.; 点3
*MAIN
; 線分移動
keyT = 65,68,87,83,69,81 ;ADWSEQ
repeat 3
getkey key,keyT(cnt*2) : if key { sp.cnt += speed : ep.cnt += speed }
getkey key,keyT(cnt*2+1) : if key { sp.cnt -= speed : ep.cnt -= speed }
loop
; 面回転
stick pad, 15 : if pad&15 {
if pad&9 { rad = 0.01 } : if pad&6 { rad = -0.01 }
if pad&5 { axis = 0,1,0 } : if pad&10 { axis = 1,0,0 }
d3vrotate f.0,f.1,f.2, f.0,f.1,f.2, axis.0,axis.1,axis.2, rad
d3vrotate f.3,f.4,f.5, f.3,f.4,f.5, axis.0,axis.1,axis.2, rad
d3vrotate f.6,f.7,f.8, f.6,f.7,f.8, axis.0,axis.1,axis.2, rad
}
; ★ここがお目当ての部分★
; 分からない所はデバック表示し易い用、関数化してないので色々見てみて下さい
; ---------------------------------------------------------------
hit = 0
; ★1)ここから平面と線分の判定
normal nv, f ; 面の法線を求める
vsub v1, sp, f : vsub v2, ep, f ; 面の適当な点から線分の開始、終了点までのベクトル
d1 = dot(nv, v1) : d2 = dot(nv, v2) ; 面の法線と内積(面に対して表か裏かを求める)
if d1*d2 <= 0.0 { ; d1,d2の符号が違えば貫通している
hit = 1
; ★2)ここから面(3角ポリコン)に含まれるか判定
; 内分点 ★3)接触した位置がipに入る。
m = absf(d1) : n = absf(d2) : t = m + n
repeat 3 : ip.cnt = (sp.cnt * n + ep.cnt * m) / t : loop
repeat 3 ; 辺と接触点の外積が面の法線と一致したら含まれる。
on cnt goto *l0, *l1, *l2
*l0
e = f.3 - f.0, f.4 - f.1, f.5 - f.2 ; ベクトル:点1〜点2
p = ip.0 - f.0, ip.1 - f.1, ip.2 - f.2 ; ベクトル:点1〜接触点
goto *l_check
*l1
e = f.6 - f.3, f.7 - f.4, f.8 - f.5 ; ベクトル:点2〜点3
p = ip.0 - f.3, ip.1 - f.4, ip.2 - f.5 ; ベクトル:点2〜接触点
goto *l_check
*l2
e = f.0 - f.6, f.1 - f.7, f.2 - f.8 ; ベクトル:点3〜点1
p = ip.0 - f.6, ip.1 - f.7, ip.2 - f.8 ; ベクトル:点3〜接触点
*l_check
cross n, e, p
if dot(nv, n) < 0 : hit = 0 : break
loop
}
; ---------------------------------------------------------------
; 描画
gsel 1 : d3setcam 0, 20, 0, 0, 0, 0 : gosub *DRAW
gsel 2 : d3setcam 20, 0, 0, 0, 0, 0 : gosub *DRAW
gsel 3 : d3setcam 0, 0.0001, 20, 0, 0, 0 : gosub *DRAW
t = 0.001*d3timer()
gsel 4 : d3setcam cos(t)*20, sin(t)*20, 10, 0, 0, 0 : gosub *DRAW
gsel 0 : repeat 4 : pos (cnt\2)*400, (cnt/2)*400 : celput cnt+1 : loop
rgbcolor $888888 : line 0, 400, 800, 400 : line 400, 0, 400, 800
pos 4, 4 : rgbcolor $FFFFFF
mes "線分の移動: X:[AD], Y:[WS], Z:[EQ]", 4
mes " 面の回転: カーソルキー", 4
redraw 1 : await 16 : redraw 0
goto *MAIN
*DRAW
d3setlocal 0,0,0, 1,0,0, 0,0,1, 0,1,0
; 描画
rgbcolor $333333 : boxf
; 軸
rgbcolor $FF5555 : d3line 8,0,0,0,0,0 : d3mes "X", 8.4, 0, 0
rgbcolor $55FF55 : d3line 0,8,0,0,0,0 : d3mes "Y", 0, 8.4, 0
rgbcolor $5555FF : d3line 0,0,8,0,0,0 : d3mes "Z", 0, 0, 8.4
; 面
if hit { col = $FF0000 } else { col = $FFFFFF } : rgbcolor col
d3pos f.6, f.7, f.8 : d3lineto f.0, f.1, f.2 : d3lineto f.3, f.4, f.5 : d3lineto f.6, f.7, f.8
_x = f.0, f.3, f.6, f.6 : _y = f.1, f.4, f.7, f.7 : _z = f.2, f.5, f.8, f.8
gmode 3,,,64 : d3square _x, _y, _z
; 法線
unv = nv.0, nv.1, nv.2 : fmid mid, f : vunit unv : unv = unv.0*5, unv.1*5, unv.2*5
d3line mid.0, mid.1, mid.2, mid.0+unv.0, mid.1+unv.1, mid.2+unv.2
; 線分
rgbcolor $00FFFF : d3line sp.0, sp.1, sp.2, ep.0, ep.1, ep.2
rgbcolor $FF55FF : d3circle sp.0, sp.1, sp.2, 0.1, 1 : d3mes strf("\nd1:%+.1f", d1), sp.0, sp.1, sp.2
rgbcolor $FFFF55 : d3circle ep.0, ep.1, ep.2, 0.1, 1 : d3mes strf("\nd2:%+.1f", d2), ep.0, ep.1, ep.2
rgbcolor $880088 : d3line f.0, f.1, f.2, f.0+v1.0, f.1+v1.1, f.2+v1.2
rgbcolor $888000 : d3line f.0, f.1, f.2, f.0+v2.0, f.1+v2.1, f.2+v2.2
if hit { rgbcolor $00FFFF : d3circle ip.0, ip.1, ip.2, 0.2, 1 }
return