0

我正在为游戏编写“重播系统”,我想知道如何存储录制的帧?

至于现在我有这个代码/结构(注意:这个代码被缩短了):

struct Point4D { float x, y, z, w; };
struct Point3D { float x, y, z; };
struct Point2D { float x, y; };
struct QuatRot { Point4D Front,Right,Up; };
struct VehicleInfo
{
    Point3D     Pos,Velocity,TurnSpeed;
    QuatRot     Rotation;
};
namespace Recorder
{
    struct FrameInfo
    //~380 bytes / frame| max 45600 bytes @ 120 fps
    //max 3.7 GB raw data for 24 hours of recording, not bad..
    {
        std::chrono::high_resolution_clock::duration time;
        VehicleInfo Vehicle;
        int Nitro;
        float RPM;
        int CurrentGear;
    };

    std::deque<FrameInfo> frames;
    FrameInfo g_Temp;

    void ProcessRecord()
    {
        //record vehicle data here to g_Temp
        frames.push_back(g_Temp);
        return;
    }
    //other recording code.......
};

我在想的是,制作一个原始字节数组,将其分配给双端队列容器的大小,用 memcpy 将它们从双端队列复制到数组,然后将所有数组字节写入文件。

然后,如果我想读取我的记录数据,我只需读取文件的字节并将它们分配给一个新数组,然后使用 memcpy 将数组内容复制到一个双端队列..

这很像..好吧.. C方式?必须有其他方法来做到这一点,将数据存储在文件中,然后将其读回双端队列(也许使用一些 C++11 功能?)。

我将如何做到这一点?

您推荐哪种方法?

如果这很重要,我正在使用 Windows。

4

2 回答 2

1

memcpy是过早的优化。

从磁盘读取内容时,您的瓶颈是磁盘 IO,而不是将其从内存的一部分复制到另一部分。

修复您的数据结构,使其使用固定大小的数据结构(而不​​是int使用 32 位 int 等)。

不要std::chrono::high_resolution_clock::duration用二进制写——库更新可以完全改变它的大小,而不用眨眼或流泪,更不用说它的意义了。写出ms或其他东西,因此含义始终保持不变,以(例如)64位整数。然后,您可以将其读回您的std::chrono::high_resolution_clock::duration.

序列化时总是写出版本号和结构大小,因此反序列化甚至可以处理基本的版本控制。

我会写一个“流”和“从流”。“to stream”写出版本号和大小。“从流”读取版本号和大小,加载当前版本和流版本中的每个字段,清除剩余的,然后从流中读取剩余的数据。

如果你发现你需要更高的性能,你会注意到你的车的位置和角度会比齿轮更频繁地变化。此外,丢弃在现有帧之间合理插值的帧会大大减少重播格式的大小(根据您的描述,这不像是在重播中运行物理)。最后,如果你有一个一致的物理模型,那么只存储用户输入和基于它的重放是可能的(但这很难实现)。

其他疯狂:只需调用相关结构即可替换 SRECORDASSIGN operator=0x4C像应用于指针这样的幻数是愚蠢的,并且几乎总是可以用简单的结构成员访问来替换。

于 2013-02-28T23:27:38.467 回答
0

如果我正确解释了您的问题(我很累,所以如果我错了,请发表评论),您想在文件中写入和读取您的录音。

这可以通过任何结构轻松完成:

struct Foo
{
   float bar;
   int baz;
};
std::ostream& operator<<(std::ostream& stream, const Foo &foo)
{
   stream << foo.bar << " " << foo.baz;
}
std::ofstream& operator<<(std::ofstream& stream, Foo &foo)
{
   stream.write(reinterpret_cast<char*>(&foo.bar), sizeof(bar));
   stream.write(reinterpret_cast<char*>(&foo.baz), sizeof(baz));
}
std::ifstream& operator>>(std::ifstream& stream, Foo &foo)
{
   stream.read(reinterpret_cast<char*>(&foo.bar), sizeof(bar));
   stream.read(reinterpret_cast<char*>(&foo.baz), sizeof(baz));
}

你可以用

#include <fstream>
#include <iostream>

int main()
{
   Foo foo;
   foo.bar = -1.2f;
   foo.baz = 37;
    std::cout << foo << "\n";
   std::ofstream output;
   output.open("myfile", std::ios::binary);
   output << foo;
   output.close();
   std::ifstream input;
   input.open("myfile", std::ios::binary);
   input >> foo;
   input.close();
   std::cout << foo << "\n";
}

有关std::basic_ostream::writeand的更多信息std::basic::istream::read,我建议查看cppreference.com

于 2013-02-27T21:46:21.107 回答