Понимание старого фрагмента файла - для тех, кто готов - PullRequest
2 голосов
/ 02 июня 2011

Я пытаюсь получить информацию PVS (рендеринг с прямой видимостью) из старого игрового формата.У него есть документация, и я смог перевести все в код C ++ до этого момента.Эта часть, однако, сбивает меня с толку.Я провел несколько часов сегодня, пытаясь понять, с чего начать, но, увы, у меня ничего нет.Опять же, это только для тех, кто может принять вызов или может дать какой-то совет или даже псевдокод для того, как бы я это сделал.

Спасибо

Записи данных 6 (их размер 6):

Data6Size1: WORD Сообщает количество записей в поле Data6Data.

Data6Data: Либо байты, либо слова

Это сложное поле.Он содержит данные, закодированные по длине прогона, которые сообщают клиенту, какие регионы находятся «рядом».Похоже, цель состоит в том, чтобы клиент мог определить, каким мобам в зоне необходимо проверить свои координаты Z, чтобы они упали на землю (или пока они не приземлились на что-нибудь).Поскольку делать это дорого, имеет смысл делать это только для областей, которые видны игроку, вместо того, чтобы делать это для всех мобов во всей зоне (неоднократно).

Я встречал только данные, гдепоток представляет собой список байтов вместо слов.Следующее обсуждение описывает RLE, кодирующее поток BYTE.

Идея здесь состоит в том, чтобы сформировать отсортированный список всех идентификаторов регионов, которые находятся в пределах определенного расстояния, и затем записать этот список как поток, кодированный RLE, для экономии места.,Процедура выглядит следующим образом:

  1. Установить начальное значение идентификатора региона на ноль.

  2. Если этот идентификатор региона отсутствует в (отсортировано), перейдите к первому в списке.Запишите что-то в поток, который скажет ему, сколько идентификаторов было пропущено.

  3. Сформируйте блок последовательных идентификаторов, которые есть в списке, и напишите что-нибудь в поток, который сообщает клиенту, что естьстолько идентификаторов, которые есть в списке.

  4. Если в списке больше идентификаторов регионов, вернитесь к шагу 2.

Когдапри записи в поток записывается один или три байта:

  • 0x00..0x3E пропустить вперед с таким количеством идентификаторов региона
  • 0x3F, WORD пропустить вперед на сумму, указанную вследующий 16-битный WORD
  • 0x40..0x7F пропустить вперед на основе битов 3..5, затем включить число идентификаторов на основе битов 0..2
  • 0x80..0xBF, включаяколичество идентификаторов на основе битов 3..5, затем пропустите вперед на основе битов 0..2
  • 0xC0..0xFE, вычитая 0xC0, это множество идентификаторов регионов находятся рядом
  • 0xFF, WORDколичество идентификаторов регионов, указанных в следующем СЛОВЕ, находится рядом

Следует отметить, что tЗначения в диапазоне 0x40..0xBF позволяют пропускать и включать не более семи идентификаторов одновременно.Кроме того, они не нужны для кодирования списка регионов: они просто обеспечивают лучшее сжатие.

1 Ответ

1 голос
/ 02 июня 2011

Это моя попытка реализовать этот распаковщик.Не проверено, так как нет примеров данных для проверки ... (даже не скомпилировано)

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 s закодированы как низкие / высокие, но, возможно, этонапротив ...

...