昨日の投稿の後、別の解決策を探っていたら なかなか良い描画結果を得る方法が見つかりました。
元祖 gsquare が裏でどんな計算をしているのかなんとなく見えてきました。
しかし元祖 gsquare とは若干異なる描画結果になります。
(なんでだろ?、というか本家版の方が歪んで見えはじめたのは気のせいだろうか?)
やっていることは昨日のやつに似ていて、四角形を一様に(?)引き延ばしたらどうなるか考えます。
昨日と同様 ベクトルの嵐です。
screen 0,200,200,0
title "source"
color 255,128,0 : boxf 0,0,200,200
color 255,255,255 : boxf 2,2,198,198
color 255,128,0 : line 0,0,200,200 : line 0,1,199,200 : line 1,0,200,199
font msmincho,200,16
color 0,0,0 : pos 0,0 : mes "画"
;< gsquare >
screen 1,400,450,0
title "gsquare"
x_dst = 0,300,400,50
y_dst = 50,0,250,450
x_src = 0,199,199,0
y_src = 0,0,199,199
gsquare 0, x_dst,y_dst, x_src,y_src
font msmincho,50,16
color 255,0,0
pos 200,400 : mes "gsquare"
;< gsquareimit >
screen 2,400,450,0
title "gsquareimit"
redraw 0
gsquareimit 0, x_dst,y_dst, x_src,y_src
font msmincho,50,16
color 255,0,0
pos 120,400 : mes "gsquareimit"
redraw 1
#module testmod
#deffunc gsquareimit int wid, array x_dst, array y_dst, array x_src, array y_src
gmode 1,2,2
//点(x_src(0),y_src(0)), (x_src(1),y_src(1)), (x_src(2),y_src(2)), (x_src(3),y_src(3))をそれぞれA,B,C,Dとする。
//点(x_dst(0),y_dst(0)), (x_dst(1),y_dst(1)), (x_dst(2),y_dst(2)), (x_dst(3),y_dst(3))をそれぞれA’,B’,C’,D’とする。
→AB = x_src(1)-x_src(0), y_src(1)-y_src(0)
→DC = x_src(2)-x_src(3), y_src(2)-y_src(3)
→AD = x_src(3)-x_src(0), y_src(3)-y_src(0)
→BC = x_src(2)-x_src(1), y_src(2)-y_src(1)
→A’B’ = x_dst(1)-x_dst(0), y_dst(1)-y_dst(0)
→D’C’ = x_dst(2)-x_dst(3), y_dst(2)-y_dst(3)
→A’D’ = x_dst(3)-x_dst(0), y_dst(3)-y_dst(0)
→B’C’ = x_dst(2)-x_dst(1), y_dst(2)-y_dst(1)
len_A’B’ = sqrt(→A’B’(0)*→A’B’(0) + →A’B’(1)*→A’B’(1))
len_D’C’ = sqrt(→D’C’(0)*→D’C’(0) + →D’C’(1)*→D’C’(1))
if len_A’B’ > len_D’C’ : L’ = len_A’B’ : else : L’ = len_D’C’ ;A’B’,D’C’のうち長い方の長さをL’とする。
//A’B’上を動点P’がA’→B’の向きに動く。
//D’C’上を動点Q’がD’→C’の向きに動く。
//両者のリズムは同じである。すなわち、同時刻において (A’P’ : P’B’) = (D’Q’ : Q’C’) が満足される。
//□ABCD上でP’,Q’に対応する点をそれぞれP,Qとする。
num_rep1 = int(L’)+1
Δu = 1.0/num_rep1
u = 0.0
repeat num_rep1
→AP = u*→AB(0), u*→AB(1)
→AQ = →AD(0) + u*→DC(0), →AD(1) + u*→DC(1)
→PQ = →AQ(0) - →AP(0), →AQ(1) - →AP(1)
→A’P’ = u*→A’B’(0), u*→A’B’(1)
→A’Q’ = →A’D’(0) + u*→D’C’(0), →A’D’(1) + u*→D’C’(1)
→P’Q’ = →A’Q’(0) - →A’P’(0), →A’Q’(1) - →A’P’(1)
len_P’Q’ = sqrt(→P’Q’(0)*→P’Q’(0) + →P’Q’(1)*→P’Q’(1))
//P’Q’上を動点R'がP’→Q’の向きに動く。
//□ABCD上でR’に対応する点をRとする。
num_rep2 = int(len_P’Q’)+1
Δv = 1.0/num_rep2
v = 0.0
repeat num_rep2
//Rの色をR’に転送
pos x_dst(0) + →A’P’(0) + v*→P’Q’(0), y_dst(0) + →A’P’(1) + v*→P’Q’(1)
gcopy wid, x_src(0) + →AP(0) + v*→PQ(0), y_src(0) + →AP(1) + v*→PQ(1)
v += Δv
loop
u += Δu
loop
return
#global
モジュール自体はdishでも動くはずです。
これはプロトタイプですが、半透明コピーも実装すれば元祖 gsquare っぽくなります。
但し激遅です。このサンプルでも数百msec要している気がします。(スクリプトですから、当然。)
一発芸的な使い方なら問題ないですがアニメーションには厳しいかと。
d3moduleのテクスチャ表示部分を改造してgsquareの代わりにgsquareimitをセットしても速度的にキツイはずです。
続いて、2つ目の質問に対する私なりの回答です。
否定的ですが、無理だと思います。
screen0 to screen0 のgsquareコピーに希望を託すも、真っ白けです。
どうにかしてbufferにちょっかい出せないかと無い知恵を絞って考えたことがありますがどうにもなりませんでした。
せめてscreen0に対してbmpsaveが使えれば、
screen0 描き描き → bmpsave → bufferにロード → 使い放題
となるんですが。
いや、せめてpgetだけでも使えれば、
screen0 描き描き → pgetで情報収集 & bmpファイルのバイナリデータを自前で作成 & bsaveで出力 → bufferにロード → 使い放題
となるんですが、pgetすらも使えないようです(p"set"は許されるのにp"get"許がされないなんて...)。
八方塞がりな感じがします。
厳しい制約の中でいかにinterestingなものを作るかということもdishの醍醐味なのかもしれませんね。
あれこれ言ったものの結局、質問者さんの満足できるソリューションを提案できませんでした。