v55の パックマンもどき(その3) で気になった気泡とヘアラインを対策してみました。
まず「気泡」問題。
以前、 気泡 気泡 その2 で割としっかり対策したはずの「つぶつぶ」の表示が、 またしても出てる感じです。
カットアンドトライで状況を再現してみます。 パックマンのpac.yamlから再現する箇所を絞りこんでいくと、、、
$ cat bubble.yaml all: - kind: or args: - kind: pipe rtd: { base: 0.1, diff: 0.3, reflect: 0.5, reflact: 0.2, density: 1, reflect_backside: False } m2g: - ax.zoom_z(0.5) - ax.slide_z(-0.5) - ax.zoom_all(0.5) # EOF $ ./cg.py eyep=[0,2,-0.5-1.5],0,1 eyet=[0,0,-0.5] yaml=bubble.yaml data_name=all name=out_v56/b n=1 show_sec=-1 div=2
ところがこれ、OR演算してないと再現しません。
bubble.yaml を
$ cat bubble.yaml all: - kind: pipe rtd: { base: 0.1, diff: 0.3, reflect: 0.5, reflact: 0.2, density: 1, reflect_backside: False } m2g: - ax.zoom_z(0.5) - ax.slide_z(-0.5) - ax.zoom_all(0.5)
に書きかえてためしてみると
$ ./cg.py eyep=[0,2,-0.5-1.5],0,1 eyet=[0,0,-0.5] yaml=bubble.yaml data_name=all name=out_v56/bb n=1 show_sec=-1 div=2
ということは、物体の演算箇所があやしい。 cross.c cross_op()関数あたりにデバッグアウトを入れて確認していくと、 ここ。cross_op_ins()関数でした。
: }else if(n == 1){ r->t = r->ts[0]; line_on_line_p( &r->l, r->t, r->p ); cross_get_nv( d->kind, &d->l2g, l_g, 0, r ); r->flags = 0; area_ins( a, r->t, r, sizeof(*r) ); if(r->ang_nv_eyev >= 0){ area_not(a); } }else{ /* n == 2 */ int i; for(i=0; i<2; i++){ r->t = r->ts[i]; line_on_line_p( &r->l, r->t, r->p ); r->flags = 0; if( prev_idx == r->idx && fabs(r->t) < fabs(r->ts[1-i]) ){ r->flags |= CROSS_FLAG_PREV; } area_ins( a, r->t, r, sizeof(*r) ); } } :
交点が2つの場合がある、球、円柱、円すいは、prev_idx を CROSS_FLAG_PREV に反映できてましたが、 平面系の交点が1つの場合に処理が抜けてました。
なので、モンスターの円柱の底面の平面の円の部分。 ここに気泡が出てたと。 対策しておきます。
続いて、「ヘアライン」問題。
カットアンドトライで絞って再現してみると。
$ cat hair_line.yaml all: - kind: or args: - kind: pipe rtd: { base: 0.1, diff: 0.3, reflect: 0.5, reflact: 0.2, density: 2 } m2g: - ax.rot_y(90) - ax.slide_y(2) # EOF $ ./cg.py eyep=[0,-50,20],0,1 yaml=hair_line.yaml data_name=all name=out_v56/h n=1 show_sec=-1 div=2
これで再現します。
そして、これまたOR演算をはずすと...
$ cat hair_line.yaml all: - kind: pipe rtd: { base: 0.1, diff: 0.3, reflect: 0.5, reflact: 0.2, density: 2 } m2g: - ax.rot_y(90) - ax.slide_y(2) # EOF $ ./cg.py eyep=[0,-50,20],0,1 yaml=hair_line.yaml data_name=all name=out_v56/hh n=1 show_sec=-1 div=2
これまた cross.c の物体の演算箇所にデバッグアウトを入れて、 area.c の area_show() を呼び出して確認していくと、、、
原因はここでした。
: }else if(n == 1){ r->t = r->ts[0]; line_on_line_p( &r->l, r->t, r->p ); cross_get_nv( d->kind, &d->l2g, l_g, 0, r ); r->flags = 0; /* --> さっき気泡対策した箇所 */ if( prev_idx == r->idx ){ r->flags |= CROSS_FLAG_PREV; } /* <-- さっき気泡対策した箇所 */ area_ins( a, r->t, r, sizeof(*r) ); if(r->ang_nv_eyev > 0){ /* ヘアライン問題の原因 ここ */ area_not(a); } :
なんと、さっき対策したばかりの箇所の直後の位置。
原因はここで、問題は r->ang_v_eyev の値が 0 の場合に、 ヘアラインが出てしまうのですが、、、
問題は、その対策です。 果たして、r->ang_nv_eyev >= 0 とするのが正解か?
例えば、物体「円柱」はdat.pyで展開されて、 内部的に「円柱の側面」、「円柱の上面の円」、「円柱の底面の円」のAND演算 として実現してます。
このAND演算に限れば、 r->ang_nv_eyev > 0 の箇所を、 r->ang_nv_eyev >= 0 に修正する対策で良さそうです。
でももしOR演算で物体を構成する場合なら、 r->ang_nv_eyev == 0 の場合は、area反転しない方が良いのでは?
でもでも、現状では、物体をOR演算で構成する場合が無いのでは?
まぁとりあえず、 趣味のプログラミングなので、 安易に対策して様子見です。
$ mv rt_v55 rt_v56 $ cat v56.patch | ( cd rt_v56 ; patch -p1 ) $ cd rt_v56 $ make clean $ make
パックマンのデータで気になった「ちょうど」なアングルの静止画を確認してみます。
$ ./pac_dat.py $ wget http://kondoh2.html.xdomain.jp/rt/pac.log $ mv pac.log pac/ $ ./pac_dat.py $ ./cg.py eyep=[0,0,20],[50,50,10],20 sec=30 yaml=pac.yaml data_name=all name=out_v56/pac_tst3_ fps=0.2 :
v55の画像、v56の画像の順で並べてみます。
もともと底面の気泡は確認できない角度でしたが、、、 ヘアライン。一部改善されたものの、まだ出てます。
まだヘアライン対策、十分ではないですね。
気泡の方も確認してみます。
v54のこのアングル。 まぁ、これだと元々あまり気泡も気にならない感じですが、、、 以前のv54の実行時のパラメータが
$ ./cg.py eyep=[0,0,0],[60,60,40],10 sec=20 yaml=pac.yaml data_name=all name=out_v54/pac
30pfs 20秒で600コマ中の97コマめなので
時刻 20*(97-1)/600 = 3.2秒
$ ./cg.py eyep=[0,0,0],[60,60,40],10 sec=20 yaml=pac.yaml data_name=all name=out_v56/pac init_sec=3.2 n=1 show_sec=-1
モンスターのログデータの先頭の時刻の処理をちょっと変えてた気がするので、 若干絵が異なってしまいましたが、、、 底面の気泡は無事消えましたね。