マーマレードSDKの固定小数点演算

少し前、ハブラーに「マーマレードSDKを使用して3Dに没頭している」という投稿があり、多くの質問がありました。 まず第一に、これは関数で送信されたマジック16進数に関するものでした。 固定小数点コンピューティング。 このトピックはインターネット上ではあまり説明されていないため、実験しなければなりませんでした。 興味があれば、猫へようこそ。



最初の部分。 整数スタイルの座標


商用ゲーム開発で長年の経験があり、5月にトーラスを(元の位置に)素早く投げて、マーマレードプラグインでエクスポートしました。 これに続いて、より魅力的な質問がありました-ビューマトリックスとパースペクティブマトリックスを設定するための魔法の整数値です。 答えは主に、モデルのロード方法とMayaの浮動座標が整数値に変換される方法に依存します。 もちろん、最初はマクロIW_FIXED_FROM_FLOATについて考えました。これは、ところで1.fを0x1000に変換します(この知識は、正規化されたベクトル、つまり長さが0x1000のベクトルを理解するのに役立ちます)。 私はあなたを苦しめることはせず、私の試みについて話しません。結果をお伝えします。 インポート時には、そのようなマクロは適用されませんが、フロートは単純に全体に縮小されます。 小数点以下をすべて切り捨ててください。 したがって、Mayaに戻って、より大きなトーラスを作成します。 まあ、私は何万もしました。 しかし、ここにはありませんでした! すべてが有望なマトリックスを分割(またはむしろカット)します。 IwGxSetFarZNearZは引数としてint32を受け入れますが、最大zFar 0xffffのみ​​を許可し、オブジェクトのサイズに制限を課していることがわかりました。 それでは、十分な精度とzFar制限のバランスをどのように選択しますか? 私の意見では、オブジェクトの最適なサイズは100〜1000の範囲になります(囲まれたスペースでは1000〜10000が可能です)。 これは、単位がセンチメートルであるMayaの寸法とよく一致しています。 たとえば、180 cmの人物を作成すると、ほとんどのシーンで十分な精度になります。 もちろん、1 cmの精度で詳細な顔をモデル化することはできませんが、幸いなことに(または残念ながら)モバイルプラットフォームでは、シーンで人の顔を見る必要がなく、同時に私たちから300メートル離れた船でも見ることができます。



マルレゾンバレエの第2部。 整数スタイルのコーナー


コーナーを使用すると、すべてが簡単になります。 座標と同様に、角度を整数に変換するための対応するマクロIW_ANGLE_FROM_DEGREESがあります。 回転行列に整数を使用するときに問題が発生する可能性がある場合、問題がすぐに発生します。 簡単なテストが示すように、Mayaからのアニメーションは問題なくエクスポートされ、フロートのすべてのターンは整数値を持つ対応するマトリックスに変換されます。 手動で変換することを覚えておく必要がある唯一の場所は、マトリックスをシェーダーに転送するときです。 ところで、マーマレードのシェーダーはサポートされていません。すべてを自分で記述する必要があります。



第三部。 批評(オプション)


結論として、この記事の冒頭で述べた投稿を少し批判したいと思います。 一般に、この記事の研究と執筆のインスピレーションをくれた著者に感謝します。

それでも、大量の質問を引き起こすプログラムの小さな部分を投稿することはできません。また、「経験の浅いプログラマーにとってもコードは非常に簡単です」というポストスクリプトを使用しても投稿できません。 たぶん私は経験の浅いプログラマーではないかもしれません。 最初の行は質問を提起しました

CIwSVec3 dd(0xFF, 0xFF, 0xFF); IwGxSetLightDirn(1, &dd);
      
      





(1,1,1)だけでなく、ベクトルのすべてのコンポーネントが0xFFなのはなぜですか? それは意識的なものですか、それともコピー&ペーストのコストですか? たぶんベクトルを正規化する必要がありますか? ちなみに、関数名の最後の文字nは、ヒントとして...説明を読み、実際に-ベクトルを正規化して転送する必要があります。 明らかに、ベクトル(0xFF、0xFF、0xFF)は正規化されていません。固定マーマレードシステムの単位は0x1000であることを上で述べました。 例のベクトルの長さは明らかに短くなっています。 正規化を追加-そして出来上がり、照明が正常に動作し始めます。 ちなみに、ボックスではなくMayaからトーラスをエクスポートしたのは無駄ではありませんでした。作成する努力は同じです。トーラスでは、照明、座標精度などの問題がすぐにわかります。 この迷惑なバグを修正した後、照明がどのように変化したかを以下に示します。





テキストに沿ってもう少し先にメガコメントがあります。その後、私はほとんどテーブルの下に滑り込みました。

IwGxSetPerspMul(...)関数にも特別な注意を払う必要があります。 これは、魚眼効果の度合いを設定する一種です。 このパラメーターをデフォルトのままにすると、画面の端に沿ったシーンは、 トイレの穴からボトルの底を見ているような印象を与えます。



著者の数学的アプローチは驚くべきものです。 栄光に満ちた科学的な突進の方法。

ヘルプでは、この関数の唯一のパラメーターを「カメラから表示面までの距離」と説明しています。 そして、なぜFOV-水平視野角、すべての白人が尋ねるように? 全能のGoogleは、マーマレードの意味を「ビューイングプレーン」で提案しました。つまり、FOVをこの距離に変換するための比較的単純な公式があります。

  int32 perspMul = IwGxGetDeviceWidth() / (2*tan(fov/2)); IwGxSetPerspMul(perspMul);
      
      





頭の中で少し考えて、なぜFOVではないのかという仮定がありました。PCとは異なり、モバイルデバイスはポートレートビューとランドスケープビューの両方を持つことができます。 さらに、ジャイロスコープはリアルタイムで切り替えることができます。 このアプローチにより、ビューの変更を手動で処理し、毎回パースペクティブマトリックスを変更する必要がなくなります。



さらに進む...

  CIwMat view = CIwMat::g_Identity; view.tz = -80; view.ty = 80; view.tx = -60; view.LookAt(view.GetTrans(), CIwVec3(0, 0, 0), -CIwVec3::g_AxisY);
      
      





コードの特定の冗長性はすぐに明らかになりますが、著者からの理にかなった説明はありません。 どうして書くだけじゃない

 view.LookAt(CIwVec3(-60,80,-80), CIwVec3(0, 0, 0), -CIwVec3::g_AxisY);
      
      





書きました。 しかし、それは機能しません。 ヘルプによると、LookAtは位置を変更せず、回転行列のみを作成します。 つまり 翻訳コンポーネントは個別にインストールする必要があります。 ここでは、マーマレード開発者の庭に大きな石を投げ込みたいと思います。LookAt関数を呼び出す場合、D3DXMatrixLookAtおよびgluLookAtと同様に機能させる必要があります-私たちは地獄に慣れています。 なぜそれが機能しなかったのかを長い間理解していなかったのは私ではないと確信しています。 実際、何年もこの機能を知っているのに、なぜヘルプを読んでください:)

PS少し厄介なことが起こったので、質問がある場合は尋ねてください。 私はマーマレードの専門家ではありませんが、まだ答えようとしています。



更新:乗算、除算、三角関数などのために、対応するマクロIW_FIXED_MUL(IW_FIXED_MUL_SAFE)IW_FIXED_DIV(IW_FIXED_DIV_SAFE)、IW_GEOM_COS、IW_GEOM_SINなどを使用する必要があることを書くの忘れていました。 マクロの安全なバージョンは、int64の計算に使用され、計算中のオーバーフローを回避します。 ただし、乗算の結果はもちろんバッファをオーバーフローさせる可能性があります。 思い出させてくれたzigmar habrayuzerに感謝します。



All Articles