> 先日、stgプログラム解説サイトで三角関数はとても重いという記述を目にして
> 改めて三角比テーブルを利用したいと思いました。
GENKIさんも仰ってますが「実際にそういう状況になってから考えた方が良いですよ」というのと、
三角比テーブル(というかテーブル引き)はHSPだと十中八九逆に遅くなります。
どういったサイトをご覧になったのかは分かりませんが、
恐らくC言語やそれに類する機械語が吐ける言語(あるいはJIT)を対象としたサイトではありませんでしたか?
sin、cosなど三角関数は確かにCPUにとって重い計算処理ですが、スクリプトの実行に比べれば目立って遅くはないです。
また、機械語を吐ける言語であっても、テーブル引きの方を十分最適化して書かないと早くならないという事情もあります。
(実行するCPUアーキテクチャにもよりますし、極端な話キャッシュにうまく乗るかの話とかもあります)
…ただ、これに関しては「やってみればいい」だけの話で、ちょっと長いですが論より証拠をば。
#include "winmm.as"
//------------------------
// sinテーブル作成、分割数をあげれば精度はよくなる
#define TABLE_DIV 256
ddim sTable, TABLE_DIV+1// 演算過程で右端点があり得るので一個余計に
repeat TABLE_DIV+1 : sTable(cnt) = sin(deg2rad( 90.0 /TABLE_DIV *cnt )) : loop
//------------------------
// サンプル点、-720-720まで等分割
#define TEST_NUM 1000000
ddim samples, TEST_NUM
repeat TEST_NUM : samples(cnt) = deg2rad( 1440.0 /TEST_NUM *cnt ) -deg2rad(720) : loop
//------------------------
// 通常のsinを使った場合
ddim resultSin, TEST_NUM
timeGetTime : st = stat
repeat TEST_NUM
resultSin(cnt) = sin( samples(cnt) )
loop
timeGetTime : ed = stat
mes strf("sin[%d sample] : %d[ms] elapsed", TEST_NUM, ed-st )
//------------------------
// sinテーブルを使った場合
ddim resultTable, TEST_NUM
timeGetTime : st = stat
repeat TEST_NUM
s = samples(cnt) /M_PI
sign = 1.0
s -= double(int(s)/2)*2.0// 0 - 2
if ( s < 0.0 ) : s = -s : sign *= -1.0
if ( s > 1.0 ) : s = 2.0 -s : sign *= -1.0
if ( s > 0.5 ) {
s = sign * sTable(int((1.0-s)*2.0*TABLE_DIV))
} else {
s = sign * sTable(int(s*2.0*TABLE_DIV))
}
resultTable(cnt) = s// 代入するところまで
loop
timeGetTime : ed = stat
mes strf("table[%d sample] : %d[ms] elapsed", TEST_NUM, ed-st )
//------------------------
// 結果比較
diff = 0.0
repeat TEST_NUM : diff += absf( resultTable(cnt) -resultSin(cnt) ) : loop
mes strf("total diff =%.16f, perSample =%.16f", diff, diff/TEST_NUM)
ひとまず手元では sin=498ms、テーブル引き=2909msぐらいになりました。
勿論私が書いたテーブル引きのHSPコードに最適化の余地はあると思いますが、三角関数の計算速度に勝てる気は(少なくとも私は)してません。
とはいえ、三角関数全体の最適化ではなく、極めて限定的な状況での最適化はスクリプトと言えど余地はあります。
例えば、θ=0付近ではsinθ≒θが成立する、とか使えばsinの計算自体がなくなるので早くなります。
(昔これを使って微妙に高速化させた記憶があるので、HSPとはいえ高速化したいところは色々調べてみると面白いかもしれません)
> それだと、x軸を反転させる意味が分からない…あれ?ん?ん???
> 謎い。
あー、私も似たようなことしたことあります。
ご自分で書かれてますが多分画像の回転軸と座標系の回転軸とが一致してなかったとかだと思いますよ。
…と思って私も古いソースコード掘り起こして見たら2回マイナスかけて箇所を発見、どういうことだ……。。。
> 私はシューティング作ったことないですが、三角関数がボトルネックになったことはないですね。描画関連がよくボトルネックになります。
> 弾幕系シューティングとかだと三角関数が効いてくることもあるんでしょうか。
個人的な感覚だと描画もそうですが、HSPだったら弾幕系シューティングは素直に弾数に依存しますね。
(というより、描画に関しては2DでDirectX使うならドローコール最適化すれば早くなるのでまだ頑張れる範疇だと思ってます)
当たり判定はおろか弾の位置移動のための加減算あたりでもう限界くるかなー、ぐらいに思ってます。
当たり判定も位置計算もそれぞれ他と独立した処理で、かつ処理として削減可能なところではないので、
有効打としてはマルチスレッドぐらいしか思い浮かばないんですよね…。
話がだいぶ逸れました。
ともかく私もGENKIさんと同じく「とにかく作ってみて、重くなったら考える、もうどうにも分からなくなったら誰かに聞く」スタンスがいいと思いますよ。
目的さえしっかりしていれば割と何とかなるもんですし、誰かが思わぬ奇策を答えてくれることも多いです。