Мой мир 3D-игр хранится в плоском массиве байтов. Мир имеет 1024 x 1024 в ширину/длину и 256 высот. Таким образом, массив имеет длину 268435456 байт. Для того, чтобы получить доступ к массиву я использую указатель индекса, рассчитанный таким образом:Индексная упаковка на плоском массиве «3D» с использованием битовой маски
WORLD_WIDTH_SHIFT = 10;
WORLD_HEIGHT_SHIFT = 8;
indexPointer = (((Px << WORLD_WIDTH_SHIFT) + Pz) << WORLD_HEIGHT_SHIFT) + Py;
Я перемещаться вокруг массива во время обработки путем добавления предопределенных констант к значению индекса для повышения производительности. Движение на запад (положительная ось х) достигается следующим образом:
WEST = WORLD_WIDTH * WORLD_HEIGHT;
NORTH = WORLD_HEIGHT;
SOUTH = -WORLD_HEIGHT;
WEST = WORLD_WIDTH * WORLD_HEIGHT;
EAST = -WORLD_WIDTH * WORLD_HEIGHT;
UP = 1;
DOWN = -1;
indexPointer += WEST;
Чтобы предотвратить индекс выходящую за пределы диапазона, и к тому, что я тупо думал достичь обертку я добавил битовую маску на результат:
WORLD_ARRAY_SIZE = WORLD_WIDTH * WORLD_WIDTH * WORLD_HEIGHT;
WORLD_ARRAY_SIZE_MASK = WORLD_ARRAY_SIZE - 1;
WEST = WORLD_WIDTH * WORLD_HEIGHT;
indexPointer = (indexPointer + WEST) & WORLD_ARRAY_SIZE_MASK;
Это хорошо работает на оси X выше, но на оси z (с севера на юг) обертывание, как я обнаружил после того, как он дал некоторые мысли, очевидно, не сработает. Исправьте меня, если я ошибаюсь, но мне нужен способ выполнить битовую маску на битах, которые представляют координату z в indexPointer. Первые 8 бит - это высота, следующие 10 бит - координаты z, а окончательные 10 бит - координаты x. Есть ли способ выполнить это, не извлекая 10 бит в отдельное поле, а затем выполнить сложение и маску, а затем восстановить окончательный указатель?
Вы уверены, что это решает настоящую проблему с производительностью, по сравнению с, например, 3d-массив? Не сказать, что это определенно не так, просто интересно, насколько это изменение влияет на производительность, учитывая, что это C#. – Rotem
@Rotem: Я думаю, что если вы реализуете его как 'a [,,]', это не так уж и сложно. 'a [] [] []' - еще одна история из-за большого количества ошибок кэша. Но все же, поскольку многомерный массив делает умножения вместо сдвигов, он может замедляться. Однако я не совсем уверен, что это узкое место в OP. –
@CommuSoft Да, это то, что я получаю. Я бы предположил, что умножения не будут такими сумасшедшими, учитывая, что C# выполняет проверку границ каждого доступа. – Rotem