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

モンスターのログデータの先頭の時刻の処理をちょっと変えてた気がするので、 若干絵が異なってしまいましたが、、、 底面の気泡は無事消えましたね。