ぬるぽを見かけたら 全力でぶっ叩くのみ


by Denullpo Smasher Hammerson
カレンダー
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

2D,3Dプログラミング向け我流数学 其之肆

[過去記事]
[壹] [弐] [参]

変数に相対的な計算を重ねていくと誤差が嵩むわけで、その対策として
リフレッシュ処理が要る。具体的にどーすりゃいーのかっつーと、誤差が嵩んで
きそーなところで精度を改善してやればいい。
前回で例示した2D回転ベクトル(c,s)を加法定理で回していく場合、誤差により
"回転ベクトル"としての要件を満たさなくなる可能性がある。
この要件ってのは、cとsの関係が成す法則。任意の回転角に対して cos と sin を
求めたとき、両者にはどんな関係が成り立っているのか?

c2+s2=12

が正解。
(1じゃなくて12なのは、2乗された値であることを強調しているん)

で、誤差が嵩むとこの式が成り立たなくなるんですよ。
回転させているうち、渦巻き状に狭まっていくかもしれないし、逆に広がるかも
しれない。この問題を防ぐには、前述の式が成り立つように修正してやればよい。
特に、単位ベクトル,単位マトリクスを回転したものに対してこの手のリフレッシュを
行うことはノーマライズといって、ベクトルやマトリクスを扱うときの基本技だったり。



n=sqrt(c*c+s*s);
c=c/n;
s=s/n;

もし可能なら、下記のように修正するとよさげ。
通常、平方根を求めるよりも平方根の逆数を求める方が速く、
除算よりも乗算の方が速いんで。
(四則演算のうち、除算だけ極端に負荷かかるのは常識として覚えとき)
n=rsqrt(c*c+s*s);
c=c*n;
s=s*n;

で、このリフレッシュ処理を埋め込むわけだが、神経質に毎回実行するのも考え物。
誤差が無視できるうちは、無視していいのだ。誤差が無視できなくなりそうなときに
修正してやればよか。そんなわけで、カウンタを持たせ一定回数いぢったときに。
あとは、実際に実験しつつ調整あれ。
気になるレベルってのは、ケースバイケースなんで。
x=INPUT_X;
y=INPUT_Y;
c=1.0; // 回転角cos
s=0.0; // 回転角sin
rc=0; // リフレッシュカウンタ
rcmax=1000000; // とりあえず、100万回毎で設定

dc=cos(0.1); // 回転角変化量cos
ds=sin(0.1); // 回転角変化量sin
while(1){
    // 回転後の位置を求める
    x2=c*x-s*y;
    y2=s*x+c*y;

    // 回転角をずらす
    sc=c;
    ss=s;
    c=sc*dc-ss*ds;
    s=ss*dc+sc*ds;

    // リフレッシュカウンタが設定値に達したときにノーマライズ
    if(++rc>=rcmax){
        rc=0;
        n=rsqrt(c*c+s*s);
        c=c*n;
        s=s*n;
        }
    }

[PR]
by denullpo | 2008-04-19 21:27 | こっち関係