3

大きなモデルやその他の構造化されたバイナリデータを、古いCDベースのゲームコンソールにできるだけ効率的にロードする必要があります。それを行うための最良の方法は何ですか?データはPythonアプリケーションからエクスポートされます。これはかなり手の込んだ趣味のプロジェクトです。

要件:

  • 完全に標準に準拠したSTLに依存していません-しかし、私はuSTLを使用するかもしれません。
  • オーバーヘッドをできるだけ少なくします。とても良い解決策を目指してください。オリジナルのプレイステーションで使用でき、しかも可能な限りモダンでエレガントなものにすることができます。
  • 後方/前方互換性は必要ありません。
  • 大きなチャンクのコピーはありません-できればファイルはバックグラウンドでRAMにロードされ、後ですべての大きなチャンクはそこから直接アクセスされます。
  • 同じエンディアンとアラインメントを持つターゲットに依存するべきではありません。つまり、構造体をディスクにダンプするPythonのCプラグインはあまり良い考えではありません。
  • 個々のファイルのRAMサイズの1/3の場合と同様に、ロードされたデータを移動できるようにする必要があります。断片化が問題になる可能性があります。悪用するMMUはありません。
  • 私の注意期間は非常に短いので、堅牢性は大きなボーナスです。つまり、コードの保存部分を変更してロードを忘れるか、またはその逆なので、少なくともばかげたセーフガードがあればいいでしょう。
  • 実行時のオーバーヘッドや深刻なメモリ管理の問題がなく、ロードされたデータと実行時に生成されたデータの間の交換可能性は素晴らしいボーナスです。

私は、Pythonで解析する半計画を持っています。これは、ポインターの代わりにオフセットを持つ構造体を使用する、構文が制限されたCヘッダーであり、メインアプリの便利なラッパー構造体/クラスは、オフセットを適切に型指定されたポインターに変換するゲッターを備えています。参考文献ですが、あなたの提案を聞きたいです。

明確化:リクエストは主にデータ読み込みフレームワークとメモリ管理の問題に関するものです。

4

4 に答える 4

4

Nintendo GameCube や DS などのプラットフォームでは、3D モデルは通常、非常に単純なカスタム形式で保存されます。

  • ファイルを識別するマジック ナンバー、頂点数、法線などを含む簡単なヘッダーと、オプションでヘッダーに続くデータのチェックサム (Adler-32、CRC-16 など)。
  • 各ベクトルと法線の 32 ビット浮動小数点 3 タプルの圧縮リスト。
  • エッジまたは面の圧縮されたリスト。
  • すべてのデータは、ターゲット プラットフォームのネイティブ エンディアン形式です。
  • 多くの場合、圧縮形式は単純 (Huffman)、単純 (算術)、または標準 (gzip) です。これらはすべて、メモリや計算能力をほとんど必要としません。

このような形式を手がかりに取ることができます。これは非常にコンパクトな表現です。

私の提案は、後処理とコピーを最小限に抑えるために、メモリ内のデータ構造に最も似た形式を使用することです。それが自分でフォーマットを作成することを意味する場合は、そうしてください。あなたは極端なニーズを持っているので、極端な対策が必要です.

于 2009-11-13T09:13:56.553 に答える
3

あなたの説明のどこにも「プログラミングのしやすさ」を求めていないことに注意してください。:-)

したがって、これを作成する方法として私が思いつくのは次のとおりです。

  • データは、再フォーマットせずにディスクからメモリにブロブを簡単にプルできるように、ターゲットのメモリと同じオンディスク フォーマットである必要があります。メモリに物を入れる自由度に応じて、「ブロブ」はファイル全体になることも、ファイル内の小さなビットになることもあります。あなたのデータを細分化する方法を提案するほどよく理解していませんが、おそらくできるでしょう。ホスト側で同じエンディアンとアラインメントに依存することはできないため、ホスト側でファイルを書き込むときは、翻訳についてある程度賢くする必要があります。両方ではなく、転送の。

  • ターゲット側とホスト側のコードが一致することを少し保証するために、単一のデータ記述を提供し、ターゲット側の C コードとそこからホスト側の Python コード。ジェネレーターにプロセスで小さなランダムな「バージョン」番号を生成させ、ホスト側のコードでこれをファイル ヘッダーに書き込み、ターゲット側でそれをチェックして、一致しない場合はエラーを返すこともできます。 . (ランダム値を使用するポイントは、気にする唯一の情報ビットはそれらが一致するかどうかであり、手動でインクリメントする必要がないことです。)

于 2009-11-13T09:14:45.957 に答える
3

これは一般的なゲーム開発パターンです。

通常のアプローチは、オフラインの前処理ステップでデータをクックすることです。結果の BLOB は、最小限のオーバーヘッドでストリーミングできます。BLOB はプラットフォームに依存し、ターゲット プラットフォームの適切な位置合わせとエンディアンが含まれている必要があります。

実行時に、メモリ内の BLOB ファイルへのポインターを単純にキャストできます。ネストされた構造も扱うことができます。ブロブ内のすべてのポインター値へのオフセットを含む目次を保持している場合は、適切なアドレスを指すようにポインターを修正できます。これは、dll の読み込みがどのように機能するかに似ています。

iPhoneゲームのデータをクックするために使用する Rubyライブラリbbqに取り組んできました。

BLOB ヘッダーに使用するメモリ レイアウトは次のとおりです。

// Memory layout
//
// p begining of file in memory.
// p + 0 : num_pointers
// p + 4 : offset 0
// p + 8 : offset 1
// ...
// p + ((num_pointers - 1) * 4) : offset n-1
// p + (num_pointers * 4) : num_pointers   // again so we can figure out 
//                                            what memory to free.
// p + ((num_pointers + 1) * 4) : start of cooked data
//

バイナリブロブファイルをロードしてポインターを修正する方法は次のとおりです。

void* bbq_load(const char* filename)
{
    unsigned char* p;
    int size = LoadFileToMemory(filename, &p);
    if(size <= 0)
        return 0;

    // get the start of the pointer table
    unsigned int* ptr_table = (unsigned int*)p;
    unsigned int num_ptrs = *ptr_table;
    ptr_table++;

    // get the start of the actual data
    // the 2 is to skip past both num_pointer values
    unsigned char* base = p + ((num_ptrs + 2) * sizeof(unsigned int));

    // fix up the pointers
    while ((ptr_table + 1) < (unsigned int*)base)
    {
        unsigned int* ptr = (unsigned int*)(base + *ptr_table);
        *ptr = (unsigned int)((unsigned char*)ptr + *ptr);
        ptr_table++;
    }

    return base;
}

私のbbqライブラリはまだ準備万端ではありませんが、Python で自分で bbq ライブラリを作成する方法についてのアイデアが得られるかもしれません。

幸運を!

于 2009-11-14T05:25:59.997 に答える
0

データを BLOB として SQLite DB に保存することを検討してください。SQLite は非常に移植性が高く、軽量の ANSI C であり、C++ と Python の両方のインターフェイスを備えています。これにより、大きなファイル、断片化なし、高速アクセスの可変長レコードなどを処理できます。残りは、これらの BLOB への構造体のシリアル化だけです。

于 2009-11-13T07:40:50.983 に答える