我正试图从旧游戏格式中获取PVS(使用视线渲染)信息。它有文档,到目前为止我已经能够将所有内容翻译成C ++代码。然而,这部分让我感到困惑。我今天花了几个小时试图了解从哪里开始,但唉,我什么都没有。同样,这仅适用于那些可能需要挑战的人,或者可以提供一些建议甚至伪代码以实现这一目标。
谢谢
Data6条目(其中有大小6):
Data6Size1:WORD 告诉Data6Data字段中的条目数。
Data6Data:BYTE或WORD
这是一个复杂的领域。它包含运行长度编码的数据,告诉客户端哪些区域“在附近”。目的似乎是,客户可以确定区域中的哪些怪物必须检查其Z坐标,以便它们落到地面上(或直到它们落在某物上)。由于这样做很昂贵,所以只对玩家可见的区域执行此操作,而不是对整个区域中的所有怪物(重复)执行此操作。
我只遇到数据,其中流是BYTE而不是WORD的列表。以下讨论描述了编码BYTE流的RLE。
这里的想法是形成一个在一定距离内的所有区域ID的排序列表,然后将该列表写为RLE编码的流以节省空间。程序如下:
将初始区域ID值设置为零。
如果(已排序)列表中不存在此区域ID,请跳至列表中的第一个区域ID。在流中写一些东西,告诉它跳过了多少个ID。
形成列表中的连续ID块,并向流中写入一些内容,告诉客户端列表中有这么多ID。
如果列表中有更多区域ID,请返回步骤2.
写入流时,写入一个或三个字节:
应该注意,0x40..0xBF范围内的值允许一次跳过并包含不超过7个ID。此外,它们不必编码区域列表:它们只允许更好的压缩。
答案 0 :(得分:1)
这是我尝试实现该解包器。未经测试,因为没有用于测试它的示例数据...(实际上甚至没有编译)
std::vector<int> regions(std::vector<unsigned char>& data6)
{
int rp = 0, sz = data6.size();
std::vector<int> result;
int current_id = 0;
while (rp < sz)
{
int c = data6[rp++];
if (c <= 0x3E)
{
// 0x00..0x3E : skip forward by this many region IDs
current_id += c;
}
else if (c == 0x3F)
{
// 0x3F WORD skip forward by the amount given in the following 16-bit WORD
if (rp + 2 > sz) throw std::runtime_error("Invalid data");
int count = data[rp] + (data[rp + 1] << 8); // (NOTE: May be H/L ?)
rp += 2;
current_id += count;
}
else if (c <= 0x7F)
{
// 0x40..0x7F skip forward based on bits 3..5,
// then include the number of IDs based on bits 0..2
int keep = (c & 7);
int skip = (c >> 3) & 7;
current_id += skip;
for (int i=0; i<keep; i++)
result.push_back(current_id++);
}
else if (c <= 0xBF)
{
// 0x80..0xBF include the number of IDs based on bits 3..5,
// then skip the number of IDs based on bits 0..2
int skip = (c & 7);
int keep = (c >> 3) & 7;
for (int i=0; i<keep; i++)
result.push_back(current_id++);
current_id += skip;
}
else if (c <= 0xFE)
{
// 0xC0..0xFE subtracting 0xC0, this many region IDs are nearby
int keep = c - 0xC0;
for (int i=0; i<keep; i++)
result.push_back(current_id++);
}
else
{
// 0xFF WORD the number of region IDs given by the following WORD are nearby
if (rp + 2 > sz) throw std::runtime_error("Invalid data");
int count = data[rp] + (data[rp + 1] << 8); // (NOTE: May be H/L ?)
rp += 2;
for (int i=0; i<count; i++)
result.push_back(current_id++);
}
}
return result;
}
我认为WORD
被编码为低/高,但可能是相反的......