|
|
2021/10/6(Wed) 13:41:55|NO.94058
●HGIMG4でベクトル(fv)の反射と屈折の関数や命令を実装したい
HGIMG4には3Dプログラミング言語によくビルトイン関数として実装されている、3次元(x,y,z)のベクトルの反射と屈折の関数や命令がありません。
数学系の情報を参照したのですが、それをどうやってHSP3のスクリプトで実装すればよいか分かりませんでした。
数学に詳しい方がいましたら、HSP3のスクリプトにして教えて下さい。よろしくお願い致します。
|
|
2021/10/7(Thu) 16:15:16|NO.94067
こんにちは、
fv値の実態は配列になりますので、以下のコメントアウトと同じ意味になります。
fvset fv, 1,2,3
;fv.0 = 1.0 ; X
;fv.1 = 2.0 ; Y
;fv.2 = 3.0 ; Z
>数学系の情報を参照したのですが、それをどうやってHSP3のスクリプトで実装
たとえば、その参照された情報が C = A + B という情報でしたら
A[1,2,3], B[4,5,6]とすると以下の様に計算できます。
fvset C, 1,2,3
fvadd C, 4,5,6
;もしくは
A = 1.0, 2.0, 3.0
B = 4.0, 5.0, 6.0
C.0 = A.0 + B.0
C.1 = A.1 + B.1
C.2 = A.2 + B.2
です。fv***系の命令はadd, sub, mul, div と四則演算用意されてますので、
参照された数学系のサイトの式と置き換えると良いと思います。
>3Dプログラミング言語によくビルトイン関数として実装されている
もう少し、具体例が分かればサンプル出せるかもしれません。
例)openglのreflection関数みたいに、
入力ベクトルと、反射面の法線ベクトルから
出力ベクトルを求める様な仕様の命令が欲しい。
など。。。
|
|
2021/10/7(Thu) 16:50:23|NO.94068
返信ありがとうございます。
関数の具体例は以下のものになります。
GLSLのreflect関数(反射)
; openGL ES2.0リファレンスより抜粋
genType reflect(
genType I,
genType N
) 生成ベクトルIが法線Nを持つサーフェスで反射したもの。
reflect(I, N) == I - 2 * dot(N, I) * N
GLSLのrefract関数(屈折)
; openGL ES2.0リファレンスより抜粋
genType refract(
genType I,
genType N,
float eta
) 生成ベクトルIが屈折率etaで法線Nを持つサーフェスに対して起こす屈折のベクトル。
屈折ベクトルは次のようにして計算する。
k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
if (k < 0.0)
return genType(0.0)
else
return eta * I - (eta * dot(N, I) + sqrt(k)) * N
これをどのようにしてHGIMG4に移植したものか上手くスクリプト化できなくて悩んでいます。
|
|
2021/10/7(Thu) 18:43:05|NO.94069
取り急ぎ、反射はこんな感じでいかがでしょうか。
#include "hgimg4.as"
#module
;reflect(I, N) ※Rに結果を代入
#deffunc reflect array R, array I, array N
;I - 2 * dot(N, I) * N
; dot(N, I) この部分
dot.0 = N.0 : dot.1 = N.1 : dot.2 = N.2
fvinner dot, I.0, I.1, I.2
; 2 * dot この部分
dot.0 *= 2
; ... * N の部分
h.0 = N.0 : h.1 = N.1 : h.2 = N.2
fvmul h, dot.0, dot.0, dot.0
; I - ... の部分
fvset R, I.0, I.1, I.2
fvsub R, h.0, h.1, h.2
return
#global
mes "テスト"
fvset i, 1,-1,0 ; 入力ベクトル i
fvset n, 0, 1,0 ; 反射面の法線ベクトル n
reflect r, i, n ; 今回つくった、反射命令 rに反射ベクトルを返す
mes strf("x: %f, y:%f ,z:%f", i.0, i.1, i.2)
mes strf("x: %f, y:%f ,z:%f", n.0, n.1, n.2)
mes strf("x: %f, y:%f ,z:%f", r.0, r.1, r.2)
redraw 0
|
|
2021/10/7(Thu) 19:13:35|NO.94070
HSPには構造体やクラス、演算子のオーバーロードが無いので、
C++に近い様な記述の言語の式を移植する場合は、
この様に式を展開して一つづつ配列操作する必要があります。
|
|
2021/10/7(Thu) 22:14:38|NO.94072
屈折も用意しました。
※屈折の方は、コメント少ないですが、反射の方を移植参考にしてください。
スカラーなのかベクトルなのか意識すると、計算の置き換えが理解できるかと思います。
#include "hgimg4.as"
#module
; 反射
; reflect(I, N) ※Rに結果を代入
#deffunc reflect array R, array I, array N
;I - 2 * dot(N, I) * N
; dot(N, I) この部分
dot.0 = N.0 : dot.1 = N.1 : dot.2 = N.2
fvinner dot, I.0, I.1, I.2
; 2 * dot この部分
dot.0 *= 2
; ... * N の部分
h.0 = N.0 : h.1 = N.1 : h.2 = N.2
fvmul h, dot.0, dot.0, dot.0
; I - ... の部分
fvset R, I.0, I.1, I.2
fvsub R, h.0, h.1, h.2
return
; 屈折
; 命令名の重複ができないので、reflect2とする ※Rに結果を代入
#deffunc reflect2 array R, array I, array N, double eta
dot.0 = N.0 : dot.1 = N.1 : dot.2 = N.2
fvinner dot, I.0, I.1, I.2
k = 1.0 - eta * eta * (1.0 - dot.0 * dot.0)
if k < 0.0 {
; R = genType(0.0)
fvset R, 0, 0, 0
} else {
; R = eta * I - (eta * dot(N, I) + sqrt(k)) * N
_s = eta * dot.0 + sqrt(k)
fvset _v, _s, _s, _s
fvmul _v, N.0, N.1, N.2
fvset R, eta, eta, eta
fvmul R, I.0, I.1, I.2
fvsub R, _v.0, _v.1, _v.2
}
return
#global
mes "反射"
fvset i, 1,-1,0 ; 入力ベクトル i
fvset n, 0, 1,0 ; 反射面の法線ベクトル n
reflect r, i, n ; 今回つくった、反射命令 rに反射ベクトルを返す
mes strf("x: %f, y:%f ,z:%f", i.0, i.1, i.2)
mes strf("x: %f, y:%f ,z:%f", n.0, n.1, n.2)
mes strf("x: %f, y:%f ,z:%f", r.0, r.1, r.2)
mes "屈折"
fvunit i ; 屈折は入力ベクトルのノーマライズが必要
reflect2 r, i, n, 0.5
mes strf("x: %f, y:%f ,z:%f", i.0, i.1, i.2)
mes strf("x: %f, y:%f ,z:%f", n.0, n.1, n.2)
mes strf("x: %f, y:%f ,z:%f", r.0, r.1, r.2)
redraw 0
| |
|
2021/10/8(Fri) 21:24:06|NO.94084
スクリプト内のコメントも含めて、関数のスクリプト化の理解に大変参考になりました。
大変勉強になりました。
ありがとうございました。
|
|