Бесконечная прокрутка 3D-карты

#ios #swift #metal

#iOS #swift #Металлические

Вопрос:

У меня есть некоторый опыт работы с Metal и совсем немного с Unity, и я знаком с настройкой сеток, буферов и резервных данных для рисования; но не столько с математической / шейдерной стороной. С чем я борюсь, так это с тем, как получить бесконечный мир прокрутки. Поэтому, если я перемещаюсь далеко вправо, я вижу левую сторону и продолжаю движение.

Это будет бесшовная местность, которую игрок может прокручивать в любом направлении вечно и просто переносить.

Я не хочу дублировать все при рисовании и смещать его, это кажется ужасно неэффективным. Я надеюсь найти способ либо использовать какую-нибудь математику magic matrix, либо какой-нибудь шейдер, чтобы переносить / рисовать объекты там, где они должны, при панорамировании карты. Я повсюду искал какое-то руководство или объяснение того, как заставить это работать, но ничего не придумал.

Я знаю, что многие старые (dos) игры делали это каким-то образом, возможно ли это? Есть ли причина, по которой кажется, что индустрия отошла от этого типа прокрутки (ограничение по краям или перенос)?

Ответ №1:

Я создал простой пример, демонстрирующий то, что вы ищете (я думаю).

Основная идея заключается в том, что вы рисуете карту в повторяющейся сетке, используя drawPrimitives(type:vertexStart:vertexCount:instanceCount:) метод on MTLRenderCommandEncoder . В качестве количества экземпляров вы хотите передать количество идентичных карт, которые хотите нарисовать, расширяя его настолько, насколько это необходимо, чтобы не видеть, где оно заканчивается. В моем примере я использовал простую сетку 5×5.

Чтобы пользователь не видел края карты, мы рассчитаем его положение по модулю 1 (или независимо от размера вашей карты):

 func didDrag(dx: CGFloat, dy: CGFloat) {
    // Move user position on drag, adding 1 to not get below 0
    x  = Float(dx) * draggingSpeed   1
    z  = Float(dy) * draggingSpeed   1

    x.formTruncatingRemainder(dividingBy: 1)
    z.formTruncatingRemainder(dividingBy: 1)
}
  

Вот как это выглядит:

Комментарии:

1. Это здорово. Мой ответ, вероятно, должен был быть комментарием. Я удалил его. Это здорово.

2. Это то, что мне было нужно. Спасибо за потрясающий пример, теперь попробуем разобраться в коде. Очень круто. Спасибо

Ответ №2:

Просто продолжение того, что я на самом деле реализовал. Сначала у меня, по сути, есть массив точек x, y с высотой, типом местности и всем этим джазом. Используя некоторые простые % и дополнения / вычитания, тривиально получить узлы вокруг точки для создания треугольников

При розыгрыше я вычисляю первую показываемую точку и последнюю показываемую точку и вычисляю группы треугольников, показанных между этими точками. Первая / последняя точка учитывает перенос, тогда довольно тривиально иметь бесконечный мир переноса. Для каждой группы смещение перевода передается через единую матрицу для этой группы, которая расположит этот раздел там, где он должен принадлежать.

Я установил его через renderEncoder.setVertexBytes(amp;uniform, length:..., offset:...)