Pull to refresh
89
-0.6

Программист

Send message

Как я попробовал написать авиасимулятор

Level of difficulty Medium
Reading time 9 min
Views 13K


Давным-давно, в 2015 году я написал свою первую статью на хабр: Пишем простую* игровую физику самолёта


Статья появилась не сама по себе — я писал игру, но так её и не доделал. За предыдущие девять лет я несколько раз возвращался к проекту, что-то улучшал, но по-факту он так и остался на уровне прототипа.


В итоге я решил открыть исходники под MIT-лицензией, чтобы кто угодно мог их посмотреть или как-то переиспользовать: репозиторий на gitlab


Если интересно почитать о процессе, удачных и неудачных технических решениях и т.п. — читайте дальше.

Читать дальше →
Total votes 30: ↑30 and ↓0 +30
Comments 10

Заметки про увеличение картинок нейронными сетями

Level of difficulty Hard
Reading time 28 min
Views 5.9K


TLDR — это не готовое решение, это попытка самостоятельно разобраться, подобрать архитектуру и обучить генеративно-состязательную модель (GAN) для увеличения картинок в 2 или 4 раза. Я не претендую на то, что моя модель или путь рассуждений лучше каких-то других. Кроме того, относительно недавно стали популярны трансформеры и diffusion модели — заметки не про них.


С заметками не получилось линейной структуры повествования — есть отступления "в сторону" и уточнения. Можно пропускать нерелевантные заметки. Например, описание подготовки данных нужно, если вы хотите воспроизвести эксперименты — а в остальных случаях можно пропустить. Я написал каждую отдельную заметку по-возможности цельной и независимой от других.


Я уже был знаком со свёрточными сетками, но мне хотелось попробовать генеративно-состязательные сети. Понять, почему используют те или иные подходы. Попробовать свои идеи. Посмотреть, насколько быстро можно научить модель и насколько хорошо она будет работать.


Для обучения оказалось достаточно возможностей моего ПК. Какие-то простые эксперименты занимали десятки минут или несколько часов, самый длинный с обучением финальной большой модели — трое суток.

Читать дальше →
Total votes 16: ↑16 and ↓0 +16
Comments 9

Физика вращения 3д тел

Reading time 11 min
Views 10K

Когда я раньше задумывался о вращении в 3д, мне было неуютно. Оно казалось сложным. Вспомнить, например, эффект Джанибекова с прецессией свободно вращающейся гайки. Настало время разобраться!

В статье Вас ждут математика, физика, а заодно численное моделирование и визуализация в libgdx.

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

Читать далее
Total votes 45: ↑45 and ↓0 +45
Comments 19

Как можно взять tensorflow и смешать две картинки в одну

Reading time 6 min
Views 5.4K

Возможно, вы встречали изображения, в которых смешаны два образа. Вблизи виден один, а издалека — другой. Например, Эйнштейн и Мадонна.

Не знаю, как делались оригинальные, но я попробовал сделать нечто похожее с помощью tensorflow.

Читать далее
Total votes 10: ↑8 and ↓2 +6
Comments 13

Ностальгии пост: j2me, Gravity Defied, 64kb

Reading time 17 min
Views 34K

Эта статья не преследует никаких практических целей — просто мне стало интересно, как лет 15 назад разработчикам удавалось делать вполне функциональные приложения и игры для слабых телефонов того времени.



  • Если что, я не имею к этой игре никакого отношения.

Например, игра с картинки выше не использовала floating-point числа, так как не все телефоны их поддерживали. "3д" и физика — полностью самописные на fixed-point вычислениях поверх целых чисел. Но мне кажется, перечисление особенностей одного приложения будет не сильно информативным. Для полноты картины я немного затрону возможности телефонов, j2me платформу и заодно сравню это с современной разработкой под Android.


Кроме того, j2me — это полноценная java старой версии (кажется, 1.3), я дописал некоторые недостающие классы и смог запустить .jar файлик с игрой на своём PC. Скриншот выше — оттуда. Не скажу, что от этого есть какая-то польза — просто API для j2me было очень простым и мне захотелось попробовать.

Читать дальше →
Total votes 70: ↑69 and ↓1 +68
Comments 47

Telegram бот для персонализированной подборки статей с Хабра

Reading time 12 min
Views 6.2K

Для вопросов в стиле "зачем?" есть более старая статья — Натуральный Geektimes — делаем пространство чище.


Статей много, по субъективным причинам некоторые не нравятся, а некоторые, наоборот, жалко пропускать. Хочется оптимизировать этот процесс и экономить время.


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


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

Встроенная в сайт фильтрация по рейтингу статей не всегда удобна, так как узкоспециализированные статьи при всей их ценности могут получать довольно скромный рейтинг.


Изначально я хотел генерировать rss ленту (или даже неколько), оставляя там только интересное. Но в итоге получилось, что чтение rss показалось не очень удобным: в любом случае для комментирования/голосования за статью/добавления её в избранное приходится заходить через браузер. Поэтому я написал бота для телеграмма, которые кидает мне в личку интересные статьи. Телеграм сам по себе делает из них красивые превьюшки, что в сочетнии с информацией об авторе/рейтинге/просмотрах выглядит довольно информативно.



Под катом подробности типа особенностей работы, процесса написания и технических решений.

Читать дальше →
Total votes 21: ↑17 and ↓4 +13
Comments 2

Шпаргалка по Gradle

Reading time 7 min
Views 89K

Как мне кажется, большинство людей начинают разбираться с gradle только тогда, когда в проекте что-то надо добавить или что-то внезапно ломается — и после решения проблемы "нажитый непосильным трудом" опыт благополучно забывается. Причём многие примеры в интернете похожи на ускоспециализированные заклинания, не добавляющие понимания происходящего:


android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.habr.hello"
        minSdkVersion 20
        targetSdkVersion 28
    }
    buildTypes {
        release {
            minifyEnabled false
        }
    }
}

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


Дальнейший текст можно рассматривать как шпаргалку для тех, кто только осваивает gradle или уже забыл.

Читать дальше →
Total votes 25: ↑21 and ↓4 +17
Comments 3

Субъективное видение идеального языка программирования

Reading time 14 min
Views 22K

Дальнейший текст — моя точка зрения. Возможно, она позволит кому-то по-новому взглянуть на дизайн языков программирования или увидеть какие-то преимущества и недостатки конкретных фич. Я не буду лезть в частные подробности типа "в языке должна быть конструкция while", а просто опишу общие подходы. P.S. У меня когда-то была идея создать свой язык программирования, но это оказалось довольно сложным процессом, который я пока не осилил.


Влияние предыдущего опыта


На написание статьи меня вдохновила вот эта статья. Автор придумал свой язык программирования, и этот язык своим синтаксисом и особенностями оказался подозрительно похожим на Free Pascal, на котором и была написана реализация ВМ для языка. И это не совпадение. Языки программирования, на которых мы раньше писали, загоняют мышление в рамки языка. Мы сами можем не замечать этого, но сторонний наблюдатель с иным опытом может посоветовать что-то неожиданное или сам научиться чему-то новому.


Рамки мышления немного раздвигаются после освоения нескольких языков. Тогда в языке А вам может захотеться иметь фичу из Б и наоборот, а ещё появится осознание сильных и слабых стороны каждого языка.


Например, когда я пробовал придумать и создать свой язык, мои размышления кардинально отличались от тех, что были описаны в статье выше. Я думал о совершенно иных вещах в рамках совершенно иных терминов. Ниже я опишу фичи языка, которые я хотел бы видеть в "идеальном" языке программирования.


Мой опыт: когда-то я начинал с паскаля, впоследствии познакомился с Java, Kotlin, C++, Python, Scheme, а основными языком считаю Scala. Как и в вышеописанном случае, мой "идеальный" язык имеет много общего со Scala. По крайней мере, я отдаю себе отчёт в этом сходстве)

Читать дальше →
Total votes 60: ↑55 and ↓5 +50
Comments 321

Learn OpenGL. Урок 5.9 — Отложенный рендеринг

Reading time 17 min
Views 27K

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


Отложенное освещение или отложенный рендеринг (deferred shading или deferred rendering) обходит эту проблему и кардинально меняет то, как мы рисуем объекты. Это даёт новые возможности значительно оптимизировать сцены с большим количеством источников света, позволяя рисовать сотни и даже тысячи источников света с приемлемой скоростью. Ниже изображена сцена с 1847 точечными источниками света, нарисовання с помощью отложенного освещения (изображение предоставил Hannes Nevalainen). Что-то подобное было бы невозможно при прямом расчёте освещения:


img1

Читать дальше →
Total votes 28: ↑28 and ↓0 +28
Comments 12

Learn OpenGL. Урок 5.7 — HDR

Reading time 9 min
Views 15K

При записи во фреймбуфер значения яркости цветов приводятся к интервалу от 0.0 до 1.0. Из-за этой, на первый вгляд безобидной, особенности нам всегда приходится выбирать такие значения для освещения и цветов, чтобы они вписывались в это ограничение. Такой подход работает и даёт достойные результаты, но что случится, если мы встретим особенно яркую область с большим количеством ярких источников света, и суммарная яркость превысит 1.0? В результате все значения, большие чем 1.0, будут приведены к 1.0, что выглядит не очень красиво:



Так как для большого количества фрагментов цветовые значения приведены к 1.0, получаются большие области изображения, залитые одним и тем же белым цветом, теряется значительное количество деталей изображения, и само изображение начинает выглядеть неестественно.


Решением данной проблемы может быть снижение яркости источников света, чтобы на сцене не было фрагментов ярче 1.0: это не лучшее решение, вынуждающее использовать нереалистичные значения освещения. Лучший подход заключается в том, чтобы разрешить значениям яркости временно превышать яркость 1.0 и на финальном шаге изменить цвета так, чтобы яркость вернулась к диапазону от 0.0 до 1.0, но без потери деталей изображения.


Дисплей компьютера способен показывать цвета с яркостью в диапазоне от 0.0 до 1.0, но у нас нет такого ограничения при расчёте освещения. Разрешая цветам фрагмента быть ярче единицы, мы получаем намного более высокий диапазон яркости для работы — HDR (high dynamic range). С использованием hdr яркие вещи выглядят яркими, тёмные вещи могут быть реально тёмными, и при этом мы будем видеть детали.

Читать дальше →
Total votes 36: ↑35 and ↓1 +34
Comments 14

Learn OpenGL. Урок 5.3 — Карты теней

Reading time 19 min
Views 35K

Тень — это отсутствие света. Если лучи от источника света не попадают на объект, так как поглощаются другим объектом, то первый объект находится в тени. Тени добавляют реализма к изображению и дают увидеть взаимное расположение объектов. Благодаря ним сцена приобретает "глубину". Сравните следующие изображения сцены с тенями и без:


with_shadows_and_without


Как можно заметить, тени делают намного более очевидным то, как объекты расположены друг относительно друга. Благодаря теням видно, что один из кубов висит в воздухе.


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


Один из методов — карты теней (shadow maps) — относительно простой в реализации, используется в большинстве видеоигр и даёт достойные результаты. Карты теней не так уж и трудно понять, они довольно дёшевы с точки зрения производительности и их легко улучшить до более продвинутых алгоритмов (типа теней от точечного источника света или каскадных карт теней)

Читать дальше →
Total votes 27: ↑27 and ↓0 +27
Comments 12

Scala: parser combinators на примере парсера формул

Reading time 9 min
Views 11K

Время от времени у меня возникает желание придумать свой собственный маленький язык программирования и написать интерпретатор. В этот раз я начал писать на scala, узнал про библиотеку parser combinators, и был поражён: оказывается, можно писать парсеры легко и просто. Чтобы не превращать статью в пособие по "рисованию совы", ниже приведёна реализация разбора и вычисления выражений типа "1 + 2 * sin(pi / 2)".


Сам парсинг и вычисление выражения занимают всего лишь 44 непустых строчки — не то чтобы я сильно стремился сократить их количество, но выглядит это реально просто и лаконично. Проект на github.


Для сравнения:



Итак, если вам не терпится увидеть результат:


Ответственный за парсинг кусочек кода
object FormulaParser extends RegexParsers with PackratParsers {

    def id: Parser[Id] = "[a-zA-Z][a-zA-Z0-9_]*".r ^^ Id

    def number: Parser[Number] = "-" ~> number ^^ (n => Number(-n.value)) |
        ("[0-9]+\\.[0-9]*".r | "[0-9]+".r) ^^ (s => Number(s.toDouble))

    def funcCall: Parser[FuncCall] = id ~ ("(" ~> expression <~ ")") ^^ {case id ~ exp => FuncCall(id, exp)}

    def value: Parser[Expression] = number | funcCall | id | ("(" ~> expression <~ ")")

    lazy val term: PackratParser[Expression] = term ~ ("*" | "/") ~ value ^^ binOperation | value

    lazy val expression: PackratParser[Expression] = expression ~ ("+" | "-") ~ term ^^ binOperation | term
    ...
}

Посмотрите на следущую строчку:


def value: Parser[Expression] = number | funcCall | id | ("(" ~> expression <~ ")")

Она подозрительно похожа на описание грамматики, но это валидный код, в котором среда разработки может сразу же обнаружить и подсветить большинство ошибок.


Это возможно по следующим причинам:


  1. В scala разрешено давать методам замечательные названия типа "~", "~>", "<~", "|", "^^". Комбинация парсеров p и q записывается как p~q, а возможность выбрать один из них: p|q. Читается намного лучше, чем p.andThen(q) или p.or(q)
  2. Благодаря неявным преобразованиям (implicits) и строчка "abc" и регулярное выражение "[0-9]+".r при необходимости превращаются в парсеры.
  3. В языке мощная статическая система типов, которая позволяет ловить ошибки сразу.

Думаю, мне удалось Вас заинтересовать, поэтому дальше всё будет по порядку.


Читать дальше →
Total votes 18: ↑18 and ↓0 +18
Comments 11

Пишем простую* игровую физику самолёта

Reading time 9 min
Views 28K
* — в трёх измерениях.


Предупреждение: дальнейшие рассуждения вполне могут быть ошибочными, мой опыт ограничивается игрой в авиасимуляторы и курсом теоретической механики. Знания в аэродинамике и игровых физических движках весьма скудные. Картинка для привлечения внимания — фотография, а не скриншот.

«Что может быть проще самолёта? Подъёмная сила пропорциональна квадрату скорости, двигатель тянет вперёд, всё просто» — такая мысль пришла в мою голову летом, и я сел писать игру. Лето прошло, было собрано несколько граблей, а списочек того, что я планировал добавить в проект, очень сильно вырос.

В данной статье я попробую написать именно о физической составляющей, не отвлекаясь на графику и прочие штуки. Надеюсь, кому-то это поможет — в интернете не очень много информации на эту тему.

Читать дальше →
Total votes 24: ↑21 and ↓3 +18
Comments 15

Information

Rating
Does not participate
Location
Белград, Сербия
Registered
Activity

Specialization

Software Developer, ML Engineer
Kotlin
Scala
Java
Python
Neural networks
Algorithms and data structures
Android development
OpenGL