1

OpenGLを使用してズームして画面に印刷する機能を備えた、マンデルブロー集合を計算しています。

ご存知のように、マンデルブロー集合は長方形 (右上の点と左下の点) で定義され、「ズームイン」と「ズームアウト」するたびに、左下の点を右上に移動して次の点を変更し、右上はその逆。最終的には、これらの 2 点が互いに出会い、ズーム プロセスが終了するはずです。
多くの YOUTUBE ムービーによると、一部のムービーでは 1000X ズームに到達できることがはっきりとわかります。私のプログラムでは、X6にほとんど到達できません。デバッグ中に、マンデルブロー集合を定義する2つのポイントが互いに到達するのを見ることができます(x1,y1) = (x2,y2)
いくつか:
(x1,y1) & (x2,y2)float として定義されています。代わりに double を使用する必要がありますか? 私のマンデルブローは (512X512) ポイントで定義されています。それで十分?問題に関連しているかどうかはわかりませんが。

私が直面している別の問題は、セットを高さマップ(3Dセット)として印刷していることです。各 Y コンポーネントが、無限に達するまでにかかった反復の量を表す場合。ただし、セット全体をズームインするたびに、カメラの位置がどんどん高くなり、最終的にはカメラがセットによって消費されます。差を計算し、カメラをセットから遠ざける方法はありますか(それに応じてズームポイントから?)

セットを計算するコード:

double ratiox = instance->foundPointOnHost.x / ((instance->constVal[1][0] - instance->constVal[0][0]));;
            double ratioy = 1-instance->foundPointOnHost.z / ((instance->constVal[1][1] - instance->constVal[0][1]));;
            double xrange = instance->m_GraphConfig.xru-instance->m_GraphConfig.xld;
            double yrange = instance->m_GraphConfig.yru-instance->m_GraphConfig.yld;
            instance->m_GraphConfig.xld += 5*direction*0.005*ratiox*xrange;
            instance->m_GraphConfig.xru -= 5*direction*0.005*(1.-ratiox)*xrange;
            instance->m_GraphConfig.yld += 5*direction*0.005*(1.-ratioy)*yrange;
            instance->m_GraphConfig.yru -= 5*direction*0.005*ratioy*yrange;  

いくつかのこと:

instance->FoundPointOnHost = 拡大したい点。
instance->constVal = セットの元のサイズが含まれています (最初は [xru,yru] [xld,yld] に等しい)
(xru,yru) = 右上セットのポイント (xld,yld) = セットの左下のポイント

ありがとう!

4

2 に答える 2

1

doubleはい、可能であれば、の代わりに使用する必要がありますfloat

フロートには24ビットの仮数しかなく、精度の限界で値を乗算すると、生成された余分なビットが失われます。

FWIW、私のWebGLマンデルブロジェネレーター(floatWebGLのために制限されています)は約5000倍のズームを管理します。

于 2012-01-31T22:13:41.027 に答える
1

コードを含めていただきありがとうございます。(物事を明確にし、すべての関連情報を含めるための質問に+1)。

ズームの理論が正しいことを示しています。すべてのステップで、xrangeyrangeは一定の係数 (0.975?) でスケーリングされ、ウィンドウはウィンドウ (と)foundPointOnHost内で同じ相対位置を維持する方向に移動します。それは間違いなくズームの背後にある正しい理論です. ただし、実際には、浮動小数点演算の仕組みにより、ズームを実装する方法によって丸め誤差が急速に蓄積されます。ratioXratioY

私の経験則:

  • 2 つの浮動小数点数を乗算または除算するたびに、サイズが結果の最後のビットであるエラーが発生する可能性があります。
  • ただし、 2 つの浮動小数点数を加算または減算するたびに、最大のオペランドの最後のビットのサイズのエラーが発生する可能性があります。

作業例。(0.5,0.3) にズームしているとします。すでにズームされてxrangeおり、yrange約 0.001 です。そして、浮動小数点数 (23 ビット、小数点以下約 7 桁の精度) を使用しているとしましょう。あなたのコードでは、2 つのx値を差し引いて再計算するxrangeと、どちらも 0.5 に近い 2 つの数値を差し引いていますxrange。 0.001、xrange小数点以下 4 桁までしか正確ではありません。次に、スケーリング、比率、および追加しますxrangeウィンドウの端に戻ります (現在は約 0.00025 の量)。これも約 0.5 であるため、算術演算は 0.0000001 までしか正確ではなく、ウィンドウの端自体は前の呼び出しから不正確です。明らかに、double を使用している場合は状況が改善されますが、繰り返しますxrangeが、ループを通過するたびに精度が失われます。x6 ズーム レベルに到達するまでに、すべてを失っている可能性があります。

「トリック」は、加算と減算の数を減らし(現在、ズームステップごとに6回実行しています)、反復ごとにエラーが蓄積しないようにすることです。次のようなことをお勧めします: and を保持し、xrangeすべてyrangeのステップでエッジを再計算します: ( ratioXandは定数であり、どれがどれでどれがどれでratioYあるかを判断する必要があるかもしれません:)ratio1-ratio

xrange *= 0.975;
xld = foundPointOnHost.x - ratioX * xrange;
xru = foundPointOnHost.x + (1-ratioX) * xrange;

についても同じですy。さらに良いことに、xrangeそれ自体が乗算ごとにエラーを蓄積しない演算を使用して計算します。

// xrange = INITIAL_RANGE * SCALE_FACTOR^frame_number
xrange = exp ( log(INITIAL_RANGE) + frame_number*log(SCALE_FACTOR) );
于 2012-02-01T20:37:58.043 に答える