Just Another Sysadmin's blog (просто еще один блог сисадмина)

System log

Немного накопленного опыта в работе с трехмерной графикой
stasikos

Весьма забавно вышло с кодингом этого воксельного мирка, настолько, что я даже не решался пока что-то писать, а все-таки закончить на каком-то этапе, чтобы остановиться и проанализировать произошедшее.
Переход в 3D оказался неподъемной ношей для моего неопытного организма.

Во-первых, оказалось, что рисовать огромную кучу отдельных кубиков - неподъемная ноша для графического движка JMonkeyEngine. Да и, думаю, для любого другого. Поэтому все нормальные люди превращают кубики в большие наборы, которые называются в Майнкрафте "чанками". Это позволяет еще до рендеринга преобразовать массив кубиков в массив вершин, решить, какие стороны кубиков, в принципе, можно увидеть, преобразовать это в некий объект и загрузить для дальнейшей обработки шейдерами. Поэтому пришлось от "отдельных блоков" отказаться на этапе загрузки всего, что увидит игрок и вместо этого реализовать некоторый "менеджер чанков" и "чанки". Первый нужен для того, чтобы хранить и находить чанки вокруг игрока, решать, что их нет, запрашивать у сервера и удалять из памяти, когда они стали не нужны (игрок ушел за пределы "видимости", скажем). Второй, собственно, занимается хранением отдельных блоков и преобразованием их набора в "mesh", то есть некоторый объемный объект, который содержит несколько VBO, то есть массивов вершин, координат текстур и других данных для обработки в видеокарте.
Вот после их полной загрузки их, в принципе, можно и обновлять отдельными событиями вроде "удалить блок", "добавить блок", "изменить блок". Но тут тоже не все так гладко. В выбранном мной для простоты начинаний JMonkeyEngine3, да и, я думаю, где угодно еще, один Mesh не может содержать множества разных материалов. То есть, на него, в принципе, можно натягивать много разных текстур, используя атлас и натягивая на разные треугольники разные куски этого атласа, но сделать его часть прозрачной, а часть непрозрачной, например, уже сложнее. Все дело, видимо, в том что он целиком обрабатывается одним и тем же набором шейдерных программ. Чтобы это решить, нужно еще крепко подумать.
Первый вариант - выделять из чанка отдельно прозрачные и непрозрачные блоки, например и делать из них два разных "меша", Увеличивает количество VBO, потенциально снижая производительность рендера, зато делать с ними можно что угодно. Второй - считать весь чанк прозрачным и управлять прозрачностью отдельных блоков с помощью альфа-канала текстуры. До этого я еще не дошел и предстоит еще разобраться, какой позволит добиться правильного эффекта.

В общем, из-за перехода от отдельных блоков к чанкам, пришлось еще и реализовать загрузку чанков целиком с сервера. Конечно, это родилось не сразу, а только после того, как я заметил, что стабильной работы при наполнении чанков отдельными блоками не удается достичь, да и загрузка происходит долго (ну, хотя-бы потому что в каждом блоке передаются еще и его координаты, и после приема нужно еще найти чанк, куда его записать и место в чанке, что значительно повышает оверхед). Так что передавая просто набор блоков без координат, зная только координаты одного угла чанка, должно быть намного дешевле, да и потом просто назначить одному из полей чанка массив данных - всего одно присваивание.

Как только эта штука будет способна быстро нарисовать хотя-бы длинное плоское полюшко-поле и позволять перемещаться над ним с подгрузкой/выгрузкой, я считаю, что можно будет это считать какой-то определенной вехой и загрузить код на GitHub после некоторой чистки. Сейчас она это уже умеет, но медленно и с некоторыми багами. Но умеет.
И приступить тогда к решению следующих задач, из коих есть что выбрать.


  • Как я уже говорил, мир состоит не из тупо блоков, а из каких-то веществ в каком-то состоянии. Значит, нужно думать, где и как сохранить этот набор веществ и правила, по которым они отображаются. Прозрачные они или нет, какие у них текстуры и все такое прочее. Потом нужно научиться это рендерить. Также важно, может ли игрок двигаться внутри блоков, или должен "сталкиваться" с их границей. Сейчас он просто пролетает сквозь них, это по-своему удобно для отладки одних вещей. но неудобно для отладки других. Значит, и на сервере и на клиенте нужно обнаруживать столкновения и запрещать дальнейшее движение.

  • Следующая проблема, это, конечно, тики сервера. Сейчас я их отключил совсем. Нужно их возродить и что-то обрабатывать. Так как блоки пока стали статичными, обрабатывать их нет смысла. Одним из важных параметров мира, как правило, является энергия, например, тепловая энергия. Ее хранение и перенос. Это непростая проблема и интересно она начинает работать только если блоки разные, в том числе, по поведению. Например, нагревающийся газ расширяется. Нагревающаяся вода испаряется.

  • Это значит, что без какой-то физической модели, кроме тепловой, обойтись нельзя. Нужно вводить какие-то понятия, во-первых, силы и давления (расширяющися газ), гравитации, импульса, массы, наконец. Появление таких вещей, как гравитации, заставляет задуматься над тем, могут ли двигаться блоки и какие правила при этом действуют. Очевидно, как минимум нетвердые блоки должны двигаться. Или, скажем, не сами блоки, а их содержимое. Пока я не столкнулся еще с проблемами производительности, я бы все-таки попробовал подумать, можно ли реализовать конечную воду, которая течет в соответствии с действием гравитации, пусть даже без "просачивания" в пористые/проницаемые вещества.

  • Но все эти вещи трудно смотреть и отлаживать без возможности для игрока ставить и убирать любые блоки. То есть, нужен какой-то "админский" или "божественный" режим, похожий на креатив в Майнкрафте. Для этого нужно, конечно же, реализовать не только такие мелочи как "узнать, в какой блок сейчас смотрит игрок и в какую его плоскость", но и некоторый GUI для выбора, какой вид блока поставить. Возможно, еще какой-то UI для того, чтобы понять, что перед тобой есть.

  • Для дальнейшей отладки очень удобно было бы все-таки заиметь текстовую консоль с командами на сервере и на клиенте. И какой-то инструмент для "замера параметров" блока с помощью наведения на него, так как нет смысла передавать все параметры каждого блока и некоторые стоит все-таки передавать по запросу.

  • Также ясно, что наличие движения требует синхронизации того, что игрок видит на экране и того, что сервер посчитал у себя. Игрок должен видеть это плавно, сервер должен делать это быстро (потому что игроков может быть более одного), так что это интересная задача, даже если думать только о движении самого игрока. Сейчас, для простоты, игрок просто передает вектор своего относительного движения на каждый апдейт (по сути - фрейм) внутри клиента, что накладно, так как это сотни-тысячи сообщений в секунду. С учетом того, что двигает игрока, на самом деле, сервер, отвечая ему новыми координатами. можно прикинуть, насколько это неоптимально. Конечно, когда FPS начнет проседать, автоматически решится и эта проблема, но зачем надеяться, что ты сделаешь слайд-шоу? :)

  • Ну и конечно, за всем этим следует работа над первым этапом генерации мира, на основе самого простого трехмерного шума. Почему так? Да потому что для всех остальных фич все намного сложнее и оно требует хотя-бы их наличия. Не хотелось бы иметь мир, который после генерации и загрузки в память вдруг оказывается нестабильным по действующим законам и требует еще кучу времени, чтобы устаканиться (такое можно иногда в Майнкрафте заметить, когда вдруг в новозагруженных чанках все осыпается и начинает течь с потолка поток лавы).


Штатуш апдейт
stasikos
Пока выдалась по-странному свободная минутка, хочу рассказать про большой фейл с управлением приоритетами. Дело в том, что эта фигня с кубическим изменяющимя миром, похоже, вызвала у меня страшную зависимость, и мне хочется без остановки писать код. В связи с чем появились, похоже, проблемы со всем остальным, отклонения от привычных распорядков и это, в свою очередь, вызывает стресс. Не делайте так. Следуйте планам, ибо ущерб всей другой деятельности рано или поздно начинает сказываться в виде давления на психику, раздражения, депрессии.
Хотя, конечно, как некоторые говорят, это приносит дополнительный опыт, связанный с программированием и геймдевом, это не повод бросать другие проекты. Да и, к тому же, если бы у меня действительно получалось все писать в том темпе, в котором хочется, наверняка все было иначе. Но пока что у меня все перешло, сначала, к безудержному рефакторингу всего, разбиванию на кучу модулей, написание "инфраструктуры" для загрузки и запуска всего и, конечно, в этом всем немало багов появляется, которые не всегда удается быстро и легко вылавливать.
Чтобы решить проблему забрасывания всего остального, пришлось для этого проекта выделить отдельный контекст, чтобы не было лишнего соблазна вместо других вещей заниматься только этой.
В общем, на прошлой неделе я забросил почти все кроме работы и всякой самоучебы и до поздней ночи писал, отлаживал и опять писал. Чем все кончилось, я уже немного открыл в предыдущем посте. С тех пор изменилось мало, единственное, что я начал делать - все-таки добавил блокам понятия "фазового состояния", то есть "пустой, газ, жидкость или твердый", перешел в три измерения, удивился, как все стало намного медленнее из-за 3D. То есть, я уже по-настоящему перешел, со всеми вытекающими в виде увеличения числа итераций по блокам на глубину мира. Здесь, конечно, возник вопрос "что считать глубиной" и вообще, как сделать из такого параметра как "радиус" эту глубину, да так, чтобы мир оставался в виде куба из кубов, а не из параллелепипедов (для удобства). Лучшим решением, как мне показалось, будет вообще забить на "радиус" на этапе выделения блоков и просто считать все за пределами твердой части и атмосферы "пустым". Тем более что радиус, конечно же, намного меньше, чем половина длины окружности, и кроме него в нее укладывается и высота условного верхнего слоя "атмосферы", что лежит в районе линии Кармана, которая находится очень близко над поверхностью, если сравнить с радиусом самой планеты. А чтобы по пустым местам серверу не тикать, просто знать, что там ничего нет и не делать этого.
Конечно, в таком представлении сферического тела как параллелепипеда есть недостатки, но ими можно просто пренебречь для простоты (все-таки это не симулятор). Первый недостаток в том, что нарезка после развертки делает блоки растянутыми у центра шара и "сжатыми" у его краев. То есть, кубометр блока вмещает только долю кубометра реального шара, если говорить о чем-то возле центра планеты, и наоборот, если посмотреть где-то далеко от него.

Также пошла работа над клиент-серверным протоколом, и задуманная изначально модульность (то есть, возможность что-то выключить или добавить путем простого подкидывания файла с кодом), конечно, сразу потребовала синхронизации информации о том, что есть у сервера и клиента, так что на это тоже ушли часы работы. Зато я ожидаю упрощение процесса разработки в будущем, так как вместо ковыряния достаточно малого по объему кода сервера или клиента все ограничится только написанием очередного модуля, который будет дергаться клиентом, сервером, генератором мира и чем угодно еще, если оно требуется, и, конечно, содержать ресурсы вроде текстур. То есть, это возможность делать моды прямо из коробки.

Насчет того, почему блоков захотелось добавить пустых, в виде газов, жидкостей и твердого - сначала мне показалось, что было бы неплохо все-таки поиграть с возможностью плавить и испарять все что угодно, со всеми вытекающими интересностями, вроде того, что вода должна бы таять и замерзать не потому что это "холодный биом", а потому что холодно. Но, конечно, блок не должен, по-идее, сразу переходить весь в какое-то состояние (моментальное испарение на солнце кубометра воды? не, вы чо!), и об этом еще предстоит размышление. Для чего это нужно? Ну хотя-бы чтобы поиграться с настоящим "круговоротом воды", когда она появляется в атмосфере в результате нагрева водоемов, а потом выпадает в виде осадков. Правда, для этого нужна еще одна "фича" в виде состава блока. То есть, воздух это воздух, а не водяной пар, поэтому кроме обычного "воздуха" там должна быть вода, и должна пониматься такая вещь как относительная "влажность". Хотя, скорее, это должно было бы быть какое-то более широкое понятие, которое бы позволяло делать это с любым веществом (и можно было бы варить самогонку в гигантском самогонном аппарате). Но это вызывает одну опасность - стоит просто представить, сколько места в памяти и на диске может занимать один блок, у которого так много аттрибутов. И сколько времени может занимать итерация по ним. И чтобы экономить, нужно будет очень сильно снижать точность вычислений и хранимых значений. Но все-таки "химический состав блока" весьма интересная возможность, особенно если это игра про шахты и копание. Я говорю про ухудшение воздуха в замкнутых пространствах и возможность там тупо задохнуться, и эта возможность весьма важна. Да и грунтовые воды должны быть, все-таки, не в виде вкраплений наполненных водой пещер, а вытекать прямо из не слишком плотных стен. Наверное. Хотя до них еще нужно кучу всего понаписать.

В общем, похоже, нельзя считать блоки только твердыми или только жидкими. В твердых блоках может быть жидкость и она оттуда может вытечь или испариться. В атмосфере может быть водяной пар. В воде может растворяться воздух. Так что, в будущем, похоже придется вместо твердости или жидкости пойти в сторону просто "состава блока", имея в виду наличие нескольких компонентов в разном фазовом состоянии. А рендерить и извлекать основную часть поведения уже от того компонента, который преобладает. Попутно, конечно, подумав, как эти данные хранить компактно, не выделяя под каждый компонент кучу байт.
Да, еще "твердость", она же может быть разной. Это может быть цельный плотный кусок чего-то, а ведь еще "твердыми" свойствами может обладать какая-нибудь щебенка или песок. У такого рода вещей, конечно, свои особенности поведения должны быть. Не так как в Майнкрафте "должно падать вниз", а несколько более продвинуто, потому что, все-таки, мне бы хотелось подумать, как сделать так, чтобы падать вниз должно было все что угодно (и тут должны поныть любители парящих в воздухе островов). В общем, в будущем предстоит раздумье, как эффективно впихнуть в один блок все его свойства и особенности поведения. А потом - как быть и с рукотворными блоками тоже.

Но, надо двигаться постепенно, ведь это прототип. Что-то постоянно меняется и переделывается, выкидывается. Не пойдет такой подход - буду искать другой. Но количество хотелок, конечно, зашкаливает. Обычно это плохо кончается, судя по опыту летсплеев. :)

Не, не выйдет ничего
stasikos

Итак, я окончательно закопался со своим "невероятно изменчивым миром".
Напомню, что изначальная идея состоит в том, чтобы сделать что-то похожее на Майнкрафт, но отличающееся от него тем, что мир не является чем-то статичным, а изменяется так, что создается ощущение, будто ты находишься в таком месте, где все имеет свои последствия и изменения в одном месте так или иначе немного, но влияют на все остальное. Как - вопрос количества "законов" в этой природе.
Начал я, как было рассказано ранее, с двухмерной плоскости, которая представляла собой некую не очень точную (в силу растянутости у полюсов) развертку поверхности круглой планеты. Плоскость была разбита на квадраты 16х8 с очень хитрой целью. Дело в том, что для меня показалось важным смоделировать так же поток энергии от ближайшей звезды, но, конечно, не абсолютно точно, так как это точно не успевало бы обрабатываться с той скоростью, которая нужна. А вот 16х8 показалось идеальным размером. Дело в том, что одно полушарие, которое освещено сейчас, таким образом сотоит из 8х8 блоков, и они точно делятся на две части в любом направлении. И здесь можно найти зону, в которую лучи падают почти перпендикулярно, то есть, экватор, в котором сейчас полдень и приходит больше всего энергии, места, где солнце уже не в зените или, если смотреть с экватора в сторону полюса, более "тропический" климат. И, конечно, полярные шапки, куда ее поступает меньше всего. Далее я считаю, что блоки, в которых никого нет в данный момент, можно не "уточнять". То есть, достаточно обработать 16х8 блоков, но.
На планете кто-то есть, кто может ее наблюдать и трогать своими грязными руками. Это игроки. Изначально предполагается, что можно уметь в мультиплеер. То есть, точек, в которых может кто-то быть, много.
Чтобы зоны вокруг игроков "уточнить", применялся простой алгоритм пересечения круга (некоего радиуса восприятия игроком) и квадрата, то есть "блока". В случае пересечения считалось, что игрок "чувствует" блок и алгоритм рекурсивно спускался глубже, на уровень своей структуры 8х8, проверяя каждый внутренний блок на предмет пересечения уже с кругом радиусом в 8 раз меньше. Так достигалось постепенное увеличение точности при приближении к игроку. В минимальном радиусе обрабатываются уже конкретные единичные блоки. Все выглядит офигенно просто, но. Рост количества вычислений с ростом числа игроков, которые находятся далеко друг от друга - линейный. Однако, есть плюс - алгоритм обхода "тиками" сервера, как мне кажется, довольно легко рассыпается по отдельным потокам, лишь с учетом блокировок, которые неизбежны при влиянии соседнего блока на текущий обрабатываемый.
Для тестирования производительности применялся довольно-таки простой, но, в то же время, очень нужный изначально алгоритм постепенного "сглаживания" некоего значения между блоками. Нужный он потому, что он неплохо изображает из себя, например, растекание кубометра воды по плоскости, хотя он и предельно упрощен. Также на нем я заткнулся в одну задачу, которая также принципиально важна вообще для идеи.
Задача следующая, состоит из двух частей:
1) Игрок удаляется от блока, из-за чего точность в этом месте должна снизиться. Необходимо "свернуть" всю информацию, которая обрабатывалась перед этим с высоким разрешением в виде, скажем 8х8 блков, в одно значение, которое сохранится теперь в одном "верхнем" блоке, так, чтобы после ее обработки можно было выполнить вторую часть.
2) Игрок возвращается. Нужно снова увеличить разрешение, сделав из одного значения снова 8х8. При этом должно быть максимально достигнуто ощущение, что все обрабатывалось как раньше.
Скажу сразу, наскоком изобрести "правдоподобное" не удалось.
Далее попытался перейти в 3D, для более удобного рассматривания результатов. То что делалалось на плоскости, стало сложнее. Хотя я не сделал все структуры трехмерными (и рисовал просто "пластинку" верхнего словя), и даже не перешел к поиску способа впихнуть все вышеописанное в трехмерность, у меня уже возникла проблема, как передать клиенту только то, что он и правда может увидеть. То есть, нужен рейтрейсинг/рейкастинг или какой угодно еще алгоритм. Причем, видимо, он должен работать на сервере, чтобы не гонять лишние данные по сети. Либо, второй вариант, нужно найти все, что обрабатывалось из-за него сервером и передать всю эту кучу блоков-подблоков, а он уже пусть там сам разбирается. Тут, кстати, несколько решений пришло в голову, начиная с простого обхода некоторой зоны вокруг игрока с загрузкой только того, что "обработано", до запихивания ссылок на каждый обрабатываемый блок прямо в объект игрока для передачи прямо сейчас (он кажется проще и делает меньше дополнительных "обходов"). Оба варианта, скажем так, будут "тестироваться". Пока что тестируется второй. Однако, все равно не ясно пока, как просто и дешево потом в клиенте избавляться от "невидимого", а также более "крупных" блоков при получении мелких.

Но, в целом, создается впечатление, что со всем таким не справится даже топовое железо.


Продолжая тему предыдущего поста...
stasikos

Штука, похожая на ту, которую я так изобретаю в миру называется Sparce Voxel Octree и применяется для рендеринга сложных объектов, как оказалось. Именно похожая, а не такая же. Во-первых, у меня нету "вокселей", которые состоят из 2х2х2=8 (и поэтому octree), хотя это имеет свои плюсы. Во-вторых, дело пока не касается рендеринга.

Если же говорить о том, чем кончилось то, что я начал в прошлый раз, то за выходные там пофиксились некоторые баги, время обработки для одной "точки наблюдения" упало до примерно 20 миллисекунд (это только за счет правки багов, без оптимизаций, хотя все равно много), прикрутилось сохранение блоков на диск и загрузка с него (правда, настолько неэффективная, а может быть, даже бажная, что немного побродив, я занял гигабайта 2 на диске и создал порядка 250К файлов) , а еще выгрузка тех блоков, что уже не нужны. Также я нашел небольшую статью (http://0fps.net/2012/01/14/an-analysis-of-minecraft-like-engines/) про эту тему, однако в ней метод нашли "опасно привлекательным" и "на самом деле очень медленным", так как действительно не очень просто бывает отыскать, скажем, соседний блок. Хорошо, если он оказывается в одном "суперблоке", но если нет, приходится делать запросы "наверх", которые, при большой глубине, действительно оказываются долгими. Что актуально для настоящих octree, где "наверху" знают только 2х2х2. В случае, когда "суперблок" содержит, например, как в случе моего эксперимента 8х8, это менее актуально, на самом деле. Тем более, что в силу изменяющейся с расстоянием точности обработки, соседи становятся все крупнее.
Правда, пока не известно, как в такое впихиваются некоторые другие вещи. Например, меня до сих пор гложут сомнения, что так можно будет легко и просто обрабатывать, например, жидкости и газы, для чего нужно, как минимум, находить границы сред. Ведь я уже говорил, что у большинства подобных движков есть, например проблемы с водой, точнее с ее течением в более низкие места, вызванные "бесконечным миром" и "очень много блоков нужно пересчитать". Так как мир в моем движке, во-первых, конечен, во-вторых, все равно пересчитывается каждый тик, само собой нужно попытаться и настоящую работу с жидкостями и газами реализовать.
И так как я уже закончил, по моему мнению, с 2D, прежде чем копаться куда-то дальше в 3D опять таки придется заниматься поиском простого решения для прототипирования в 3D. Потому что писать на голых вызовах OpenGL все-таки будет очень долго.
И есть еще темы для размышления, только из того, что хотелось-бы видеть возможным:


  1. Как впихнуть в это некие сети (провода, трубы, конвейры, что угодно), по которым бы можно было передавать энергию или сигналы или предметы. Как эффективно их обрабатывать после перехода с отдельных блоков на более крупную сущность? Впрочем, наверняка это и без таких извратов как-то сначала преобразуется в один объект и соответственно обрабатывается. Однако, к сети обычно подключаются сущности, которые делают из А какое-то Б, и вот тут уже нужно крепко подумать. Можно ли, например, сделать из такой сети с сущностями достаточно простой объект, который и без блоков выполняет нужные действия. А еще, можно ли сделать так, чтобы сложность его обработки не сильно росла с размером этой сети...

  2. Как впихнуть в это мультиблочные структуры? Рано или поздно их захочется видеть и они должны как-то, во-первых, узнавать, что они правильно собраны, во-вторых, что они до сих пор целы, а в третьих - взаимодействовать всей своей тушей с окружающим миром.

  3. А еще явно обязательно захочется иметь что-то, что больше 1 блока и умеет двигаться. Ну, я не знаю. Динозавриков. Улиток размеров с 9-этажку. Мало ли что. Звездный крейсер Дарта Вейдера. Причем, что-то обязательно захочется собирать из блоков, например. Однако, такое сооружение должно не просто двигаться взад и вперед, а иметь возможность делать это, во-первых, плавно, во-вторых, плавно же поворачивать. И нужно будет обнаруживать столкновения, конечно же.

  4. И самый эпичный вопрос мне в голову пришел ночью. Скажем, у нас есть лодка, которая плавает на поверхности воды. Сейчас она находится далеко от нас, но плавает на поверхности озера, которое мы случайно осушили у себя тут. Неужели нужно хранить сущность лодки как-то отдельно, а потом проверять, влияет ли на нее какой-то процесс? Глупо как-то и неэффективно смотрится. Другой вопрос - при осушении вода должна все-таки оставаться в разных неровностях, из которых она не могла бы утечь. То есть, вытекание воды из водоема процесс не настолько простой как "да просто в этом суперблоке уровень моря меняем и все". В общем, вещи, которые кажутся естественными, вносят немало вопросов для размышления. 5+) ... много всего, чего страшно озвучивать

С учетом того, что в 2D простейшая операция, которая просто брала одно число из каждого "блока" и усредняла его с соседними заняла 20 мс, у меня уже есть сомнения в производительности того, что получится. Хотя, конечно, это быстрее обсчета всего мира. Я уже приводил пример Земли, с радиусом около 6000 км. Так вот, в итоге двухмерный мир получается размером примерно 4.5е8*2.2е8, то есть 12е12 блоков. С учетом текущих алгоритмов, которые его разбивают на 16х8 частей, а потом каждую 8-ю часть полученного постепенно разбивают на 8 и углубляются до уровня отдельного блока, который находится на небольшом расстоянии от игрока, выходит всего порядка 30 тысяч блоков. Хотя, конечно, во-первых, в 3D это будет на порядок больше, во-вторых, мне эта дистанция "высокого разрешения" кажется все-таки крайне маленькой. Но 30 тысяч это уже большая цифра. Стоит делать что-то сложнее с каждым из 30 тысяч блоков и движок просто не будет успевать делать это вовремя. Является ли это проблемой Java? Не знаю. Можно узнать, только если переписать все на С++. Чем я, возможно, и начну заниматься, ради того, чтобы вспомнить, как оно и будет ли от этого какой-то прок.
Как это не создает проблемы в Майнкрафте? Дело в том, что там не обрабатывают каждый блок, насколько я знаю. У него есть сущность TileEntity, и только она обрабатывается, причем только если чанки, в которых они находятся, загружены. Это может быть какой-то монстрик или еще что-то. Они там хранятся в списке отдельно от блоков, поэтому размер мира никак не влияет на производительность. Зато влияет количество таких, генерирующих события, объектов. И ложится все где-то на количествах порядка одной-двух тысяч, по моему.


О срывах
stasikos
Кажется, я опять немного сорвался со своего режима. Все дело в подлом программировании, которое иногда способно вызвать желание играть в игру "еще одна идея относительно этого и все". Мне все-таки захотелось проверить, можно ли в кубическом мире достаточно быстро обрабатывать глобальные процессы, не загружая весь мир поблочно в память. Почему нельзя загрузить? Ну, возьмем, например, такую планету, как Земля. Она имеет радиус около 6 тысяч километров. Это значит, что если мы хотим ее превратить в кубики, получится порядка 40*20*6 миллионов кубиков, без учета атмосферы. То есть, очень большое число, порядка триллионов. Если даже хранить блок как один байт, требуется терабайт с копейками, без учета всяких там структур данных. Сгенерировать его - я, полагаю, в зависимости от алгоритма, дело многих часов, может даже дней. Просчитывать его изменения с точностью до одного блока - невозможно в реальном времени. Идея была в том, чтобы проверить, насколько правдоподобную картину можно получить, если, скажем, генерировать и считать все большие и большие блоки по мере удаления от наблюдаемой игроком точки. Начал, конечно, с двухмерного мира, который имеет просто блоки километр*километр, то есть, в тысячу раз уменьшил Землю. Просто для удобства. И тут началось. Вроде бы все было идеально продумано, но где-то влезли какие-то, видимо, недостаточно хорошо обдуманные баги и пока что не получилось ни шиша. То есть, вроде-бы все работает на этапе рассчетов и весь мир успевает "тикнуть", без рассчетов и прочих операций, за десятки миллисекунд, на жаве, но отобразить его кусочек пока не получается. Где-то косяк с "взять вон тот блок с этими вот координатами". Хотя, конечно, и десятки миллисекунд это много. Еще и в двухмерном варианте. В общем, пока разочаровываюсь в идее, поэтому, видимо, так сильно залип в проблеме. Даже вот сюда ничего не писал. Хотя подход сначала казался очень правильным и даже казалось, что он офигенно должен масштабироваться, как на отдельные потоки, так и на разные процессы и даже физические машины. То есть, такой мир можно было бы размазать на целый кластер серверов и пускать игроков толпами. Но что-то, похоже, будь все так просто, это давно уже сделали бы.

На самом деле это важно, вовремя останавливаться и переключаться на другую деятельность, чтобы она не страдала. Работа та же. Летсплей. Обучение. И еще одна проблема - я эту задачу никак не разбил на части, она никак не спланирована и даже каких-то идей, которые возникли по мере попыток ее реализовать, я не записал. То есть, все потеряно. Хотя идей было много, и часть из них может быть полезна даже для других каких-то проектов. Вообще привычка это все записывать и обрабатывать у меня, похоже, развита не очень хорошо, потому что такое бывает часто. И не знаю, что с этим поделать, потому что это скорее касается самоконтроля и привычек. Менять и прививать новые привычки у меня пока получается плохо. А может просто очень неудачно реализован функционал добавления новых задач в текущем софте, ведь MLO написан под винду и что-то не спешит ловить нажатия хоткея, когда не активен. И иконку в трее не всегда делает. В общем, дело дрянь. Надо привыкать натыкивать новые задачи в андроиде, что не всегда удобно.

Чего, возможно, можно искать в песочнице, что считать выживанием, в принципе?
stasikos
Все-таки пытаюсь точно понять, чего хочется. То, чего искал и чего не нашел. И много ли таких же.
Майнкрафт, наверное, сначала зацепил тем, что можно сделать себе ранчо с нехилым особняком на берегу моря. Или замок на вершине горы. И вообще осваивать большую территорию, которая ничья. Плохо стало, когда некому показать и нет, перед кем выпендриваться. Скучно. Нужно было много копать и заниматься прочим микроменеджментом.
Потом моды нашлись. В модах можно было сделать такую классную штуку, чтобы выкапывать помногу и где-то далеко, а складывалось у тебя дома. И можно было все хранить в маленьком пространстве и легко искать, что нужно. И автоматический крафт по запросу. И можно было долго ковыряться. И тоже хотелось осваивать большую ничейную территорию. И тоже стало плохо, когда некому пользоваться. А потом еще и стало надоедать, что все неидеально. Океаны не высасывались, местность не опустынивалсь, гармония с природой никуда не девалась. И да, одинокий чувачок в квантовой броне не знал, куда девать бесконечные богатства, добытые индустриальными методами. Одни и те же руины, одни и те же монстры. Одни и те же заброшенные шахты. Опять скучно. Похоже, вы хотите сказать, что надо было идти на сервере играть с кем-то? Я тоже так думал. Но с этими модами, как правило, я заставлял все дико тормозить и в одиночку.

Потом они сделали кое-что интересное. Появился мод HQM, который требовал от тебя дополнительных целей. Особенно порадовал немного упоротый модпак с картой Agrarian Skies, в котором "небожители" настойчиво требовали целые составы цистерн молока, тысячи и тысячи бревен, миллионы и миллионы блоков камня из нечего. Неплохой был челленж построить автоматический завод для производства всего этого. Ну и это позволило пощупать кучу разных модов, которые раньше не пробовал, потому что они немного не той направленности. Правда, там не хватало одного - не было мира, из которого нужно это все высосать. То есть, все получалось буквально из ниоткуда, нужно было только достаточно много поставить машинок, которые делали камни из ничего. Возможность получать бесконечное количество блоков камня из одного ведра лавы и одного ведра воды, конечно, в Майнкрафте доставляет. Особенно, когда хочется говорить о реализме. Но это я отвлекся.

Как всегда бывает, в любой игре есть есть эндгейм. Не геймовер, а эндгейм. Когда у тебя уже все есть и дальше может быть только больше, даже если ничего не делать. У кого-то он наступает быстро, потому что они наигрываются еще на этапе заведения коровы и постоянной дойки молока с нее, чтобы поесть сегодня тыквенного пирога. Зависит от любопытства, задротистости и амбиций. Оригинально в МК это пойти в другое измерение и убить дракона. Достаточно сложная цель для ванильного игрока. С модами нового эндгейма не появлялось, кроме, разве что, ГрегТеха, который многие считают почему-то хардкорным и упоротым. Я бы сказал, что это нетипичный для мира Майнкрафта мод, который все пытается переделать в какой-то псевдорелистичный sci-fi. И он добавляет никому не нужный термоядерный реактор, с которым у вас, скорее всего, все, наконец, ляжет и станет тормозить, потому что он ест много дейтерия/трития, которые получаются с нужной скоростью только через несколько десятков машинок. В общем, да, упоротый, но именно этот подход не дает мне покоя. Я люблю sci-fi.

Оттягивание эндгейма, как правило, решается путем добавления, вручную, этими геймдизайнерами и прочими моддерами, кучи дополнительных фич, предметов, рецептов, машинок. Количество этих штук в итоге все равно не бесконечно, так как конечны объемы памяти компьютера, в котором нужно хранить список этих вариантов и конечны рабочие часы тех, кто это рисует и кодит. И когда все игроки пощупают все эти штуки, игра неминуемо умрет (может и раньше, если морально устареет).

Вот что действительно бы хотелось, это чтобы эти все штуки могли получаться сами собой. Я не знаю, генерироваться, придумываться, конструироваться игроком в разумных пределах, не нарушающих баланс. Подобно тому, как можно из любых блоков построить себе иридиевую избу с золотыми ставнями. Чтобы была экономика и влияние местную флору и фауну, конечные ресурсы, и, главное, чтобы продукцию было куда девать. Но, наверное, это нечто очень уж глобальное, и лучше и правда делать это в бесплатном симуляторе с хорошей графикой. Но. Во-первых, в нем уже и так куча игроков, которые все уже забрали себе, во-вторых, все происходит медленно. То есть, есть причина искать другой способ. Но сделать ускоренный симулятор симулятора с классной графикой... да, может быть. В общем, интересный вопрос: возможно ли теоретически вместо создания контента дать достаточно вольный набор законов/правил, чтобы оно как-то само... генерировало мир (это уже умеют), наполняло его интересностями (это уже умеют, кто-то лучше, кто-то хуже), возможно, создавало уникальных обитателей, приспособленных для этого мира, а потом давало возможность игроку из всего найденного придумать что-то свое. Не только построить из разноцветных кубиков себе хатку, но и сделать таким же образом работающие вещи, которые могут из А делать Б и так далее? Нет, я понимаю, продумать и написать код для такого - невероятно сложно. Еще сложнее придумать под это необременительный интерфейс. Абсолютно неподъемно превратить это в модельку для отображения на экране. Поэтому вряд-ли это путь. Но может, тогда, можно сделать добавление фич более простым занятием? Или что-то среднее?Чего, возможно, можно искать в песочнице, что считать выживанием, в принципе?Чего, возможно, можно искать в песочнице, что считать выживанием, в принципе?

Немного анализа подхода к продуктивности. И снова про идеальную песочницу.
stasikos
Конец очередной недели. Сплю все так же - обычно раньше 11, иногда раньше 12. Эффект интересный - сонливость днем пропала, вроде-бы появилась энергия. Правда, она иссякает к вечеру, даже я бы сказал, довольно быстро, уже часам к 7 (хотя 12 часов это вполне нормально, если смотреть с другой стороны). Но пока правильный сон рулит. Я вижу меньше проблем с прокрастинацией на этой неделе.
Правда, несмотря на какое-то приподнятое настроение, в конце недели всякий анализ реальных цифр уже не так радует, повторяя результат прошлой недели. И дело не в том, что "не успел", а в том что не очень много времени попадает в фокус. Большие перерывы между подходами, которые растягиваются до 15-30 минут, сожрали все время, я полагаю. А были они из-за кучи разных вещей, которые происходили дома. То появился аквариум с рыбами, то еще больше рыб. Потом с неба упала еще и черепаха. В общем, домашние во всю пытаются кого-то понянчить и склонны к неконтроллируемому накоплению всего, что плохо лежит и выгодно покупается. Пока не придумал, как это лечить.
На фоне всего этого роение мыслей по поводу того, чего бы мне хотелось попробовать реализовать (а страшно хочется сделать свой клон Minectaft почему-то) достигает пика. Однако, не хочется делать тупой клон. В голову лезут всякие разные идеи, начиная с объяснимого сюжета и заканчивая какой-то другой системой крафта. Хотя, в MC, она, возможно, наиболее удачная, потому что сочетает как визуальный "рецепт", так и компоненты, и их размер оптимален - от 4 до 9 предметов в квадратной матрице. Это относительно просто запоминать, иногда выглядит очень наглядно и дает огромное количество вариантов. Правда, в ней все очень по-игрушечному, но для игрушки это как раз хорошо. В общем, мне нравится этот подход, но во-первых его не хочется копировать, во-вторых, хочется чего-то серьезнее, реалистичнее, что-ли, выдумать.
Да и вот, с чего все начинается там? Вы появляетесь в случайном месте и в руках у вас есть волшебное ничего, чем можно рубить деревья, копать землю... Как это рубить деревья ничем? Вот мне тоже никак не лезет в голову этот факт. Ладно копать землю руками, в принципе, если очень захотеть, можно. Но голыми руками сделать из дерева бревна, а из бревен - планки...
Потом вы делаете из нарубленного голыми руками дерева деревянный топор. Голыми руками. Возможно, помогаете себе зубами и ногами. В конце концов, вы получаете деревянный топор и, самое важное - деревянную кирку. И этой деревянной киркой вы добываете себе первый камень. Из трех огромных камней в один кубометр объемом и пары палок вы голыми руками можете сделать себе теперь уже каменный топор. Да, именно так. Я еще забыл сказать, что вы эти три кубометра камня носили в карманах, пока шли от пещеры к своему верстаку. А может и больше. Ведь деревянной киркой можно не один десяток кубометров камня отрезать. Всего, при желании, вы можете переносить, по-моему, 4*10 стеков по 64 кубометра камня. 2560 кубометров камня в карманах! Если это гранит, вы способны носить в карманах 6656 тонн гранита. Нет, я все понимаю, иначе было бы очень сложно и неинтересно, наверное. Но, вообще-то, такое не очень хочется повторять один в один, хотя это офигенно играбельно.
Да, еще. Если взять бревно и обжарить его в печке, вы получите древесный уголь, который ничем не хуже каменного, то есть горит так же прекрасно. И лучше, чем сами бревна. А если насадить уголь на палку, можно получить вечный факел. В Minecraft очень мало законов из реального мира, которые соблюдаются.
На самом деле многие вышеперечисленные вещи там правили с помощью хардкорных модов. Факелы, которые делались из пропитанных креозотом кусков шерсти. В Terrafirmacraft они со временем гасли. Кто-то даже пытался ограничить размер инвентаря. Но это все полумеры. Натягивать на полностью выдуманную вселенную реальные законы природы - неблагодарное занятие.

Про Coursera
stasikos
Год у меня лежала где-то в списке "попробовать" идея посмотреть на Coursera. Наверняка, все уже посмотрели, что это, может даже взяли один-два курса и забили. Последние две недели я офигевал от того, насколько много разных курсов там есть. И первым взял Learning How To Learn, из которого кое-что, конечно же, подтвердило правильность моих подходов и я вынес немного новой информации о том, как получше учиться и не только. А потом я просто тыкал во все, что интересно. И вот, затрачивая всего около часа в день, я прошел курс Managing Your Money, который меня настойчиво пытался убедить, что кредиты это тоже хорошо, и что всем стоит подумать стать предпринимателями, затем курс тайм-менеджмента (Work Smarter, Not Harder), который ничего, в принципе, нового узнать не позволил, а затем и более сложный, но все-таки легкий Introduction To Communication Science, в котром я ожидал увидеть что-то про там, ну, сети, интернеты, но оказалось, что нет. И поэтому, наверное, курс был полезен как небольшое краткое вступление не то чтобы в передачу информации, а в то, как средства массовой информации могут воздействовать на свою аудиторию. В этом плане было полезно еще раз осмыслить, как чего происходит у нас прямо сегодня и еще раз подумать о том, как хорошо, что я не смотрю телевизор. Хотя, наверное, было бы полезно и в интернетах новости пореже читать. Но даже читая их, смотришь уже несколько трезвее. В общем, курс прикольный. Теперь мне попался курс про машинное обучение, но я только начал, и он, конечно же, посложнее предыдущих, в котром пока что все началось с того, что меня заставили поставить GNU Octave. Может пользоваться научат, а то я как-то больше умел из такого только немножко в Maple. Есть, конечно, еще десяток всяких других курсов, которые меня заинтересовали, но я решил не изучать больше двух за раз.
Конечно, забрать час в день из своего времени на получение знаний, которые не нужны прямо сейчас - не очень умная затея, и с этим надо что-то будет делать. Однако, я заметил, что бывает и так, что знание о существовании готовых методов впоследствии позволяют не изобретать колесо. В этом, в принципе, полезность любого учебного заведения, в том числе. Даже школы. То что на Coursera мне дали возможность выбрать интересные темы - это несомненный плюс. Параллельно радует незаметное дальнейшее прокачивание скилла восприятия английского на слух. Не радует, что изученные термины бывает непонятно как перевести на русский язык. То есть, смысл понятен, а сказать не получается. Но это у меня было еще когда я готовился к сертификациям от Cisco Systems.
Ну а что касается их сертификатов - не вижу смысла покупать их, так как никакой ценности кроме повешения на стену они не имеют. Так что для меня это "бесплатное обучение".

И снова про OpenGL
stasikos
Пришло время снова поныть про OpenGL. Дело в том, что я никуда не продвинулся в своих попытках изображать что-то объемное, а тем более сферу. Потому что в OpenGL3 все стало намного более низкоуровневым и без каких-то дополнительных слоев абстракций это сущий ад. Если кто такого опыта не имел, поясню. Чтобы изобрать что-нибудь, нужно задать массив вершин треугольников, из которых будет это что-то изображено. Построили? Ну, понятно, это, в большинстве своем, школьная геометрия, хоть и в трехмерном пространстве. Далее вам нужно написать шейдерную программу. На языке шейдеров - GLSL. Это такой высокоуровневый язык, похожий на C. В этой программе вы будете объяснять видеокарте, что делать с массивами значений, которые вы ей скармливаете (и не всегда это могут быть координаты вершин). То есть, возможно, применять какие-то операции с матрицами, чтобы передвинуть объект, отобразить его в перспективе, то есть, не как что-то плоско спроецированное на экран, а сделать его проекцию с учетом того, что пространство уходит куда-то вдаль и там все становится меньше. Кроме того, шейдерные программы позволяют рисовать разными цветами, налеплять текстуры, делать всякую тесселяцию (т.е. сгладить угловато-треугольниковую поверхность) и т.п. Так вот без дополнительного слоя абстракции все сводится к тому, что это все нужно написать самостоятельно и так же самостоятельно загрузить куда нужно.
И здесь мне хочется остановиться и подумать. Стоит ли продлжать пытаться сделать это с Java и JOGL на таком низком уровне, изобретая собственный трехмерный движок, или, скажем, взять какую-то, возможно унылую и отсталую абстракцию вроде JMonkeyEngine или jOGRE, или вообще пойти на С++, где выбор намного шире. Вопрос, в общем-то, имел бы простой ответ, будь у меня в последние лет пять какой-то опыт написания приложений на С++, чтобы я хотя-бы имел представление о том, что нынче есть в стандартной библиотеке и распространенных вещах вроде того же Boost. Ведь с пониманием, какие структуры данных и абстракции уже есть в языке, писать что-то сложнее хелловорлда намного проще. Тут же, у C++, есть эта самая OGRE, которую мне почему-то советуют (но я еще не смотрел).
Впрочем, никто не мешает подсматривать в код других движков и писать что-то свое, заточенное именно под задачу шариков или кубиков. Но, вынужден сказать, что уже немного опускаются руки, и хочется вообще забить на эту идею. Однако она иногда не дает нормально спать, и это заставляет ковыряться дальше. Правда, ничего целостного насчет применения не вырисовывается, и, похоже, мне просто хочется проверить некоторые концептуальные идеи сначала, да, касательно кубических миров и возможного уровня их детализации без серьезных потерь производительности. Может и зря я заморочился при этом сразу с отображением в 3D на видеокарте, хотя с таким средством наглядной демонстрации было бы проще.
Прошу ли я совета? Не думаю. Все равно я достаточно упертый, чтобы попробовать и выбрать самостоятельно, не учитывая чужое мнение. :)

Про попытки изучать OpenGL снова
stasikos
Пока выдались пара часов вчера вечером, засел за очередную задачу. Как вы помните, в прошлый раз я использовал LWJGL и нарисовал кружочек на белом фоне. Теперь мне хотелось как-то написать движение "камеры". Однако, с тех пор прошло много времени и я узнал, что, во-первых, то что я делал, это называлось Legacy OpenGL и так со времен появления OpenGL 3.0 уже не делают. Так что я начал искать новые источники знаний и примеров. А еще я попробовал использовать другую библиотеку - JOGL. К ней нашлось немало примеров "более современного" кода - https://github.com/elect86/modern-jogl-examples. Это набор примеров к книге "Learning Modern 3D Graphic Programming", и он уже точно использует новые инструкции API. А это, в том числе, шейдеры и их загрузка. В общем, кружочки и шарики я пока не смог, но в общих чертах понять, как рисуется один белый треугольник на черном фоне из первого примера я уже понял и даже догадался, как сделать его розовым. Теперь интересным опытом будет переход все-таки к рисованию трехмерных объектов вроде пирамидок, движению камеры и накладыванию текстур и создания источников света. Зачем? Все-таки не уймусь, пока не смогу отображать рандомно генерированные множества планетарных систем. А что если научить их еще и "вращаться"? Добавить туда 2-Body гравитационные взаимодействия было еще веселее. Люди даже из этого умудрились сделать игрушку, например вот: http://universesandbox.com/2/. Правда, стоит, как по мне, непомерно много, так что я ее не пробовал сам и поиграл в нее по Youtube. Не то чтобы в ней нет кучи разных интересных возможностей, просто мне кажется, это не та игра, в которую можно играть долго и с удовольствием, как чуть более дешевые KSP или Minecraft.

Но это еще не всё. Пока я жаловался на тяжкую жизнь с OpenGL, мне вообще посоветовали, что лучше бы C++ изучать, тем более что современные его стандарты уже определяют улучшенный поиск утечек памяти и даже встроенную поддержку сборки мусора. Правда, для этого нужно даже от gcc пока отказываться и пользоваться clang. Всё это очень интересно и лежит далеко за пределами того, к чему я привык и чем давно пользуюсь. Ну, вроде как свежий воздух. Это, правда, не значит, что я начну страдать сразу от двух новых направлений - OpenGL и С++11. Все-таки, думаю, поразбираться в OpenGL можно и на Java. Все равно, когда мне говорят, что на С++ все будет "быстрее", я не всегда склонен в это верить. Я бы сказал, что все, скорее всего, будет просто "плавнее", без внезапных вмешательств сборщика мусора.

Не факт, что в итоге получится новый кубический движок для очередного клона Minecraft на C++, конечно, но в итоге я надеюсь в общих чертах понять, что можно делать с помощью всего этого, и, надеюсь, применять эти знания, в том числе, для создания чего-то полезного, например, на работе.

?

Log in