Псевдо 3D-демо для Радио-86РК

Писав пост про досовскую демку команды UCL, я надеялся, что мне подскажут ее алгоритм. Увы, сначала были только “буу” на Хабре, но вот Вячеслав Славинский подогнал не просто алгоритм, а уже готовое решение.

Основные моменты реализации:

  • Формула “волны” (функция z_offset), по которой вычисляется координата Z.
  • Формула перспективы zdiv для перевода (X, Y, Z) в плоские координаты экрана.
  • Пример работы с библиотекой Processing.js для удобного моделирования 3D. Если посмотреть исходник, то это не совсем JavaScript. В это типа Java c типами и отсутствием вольностей типа опционального “;”.

А вот демка в действии.

Изучив ее вдоль и поперек, у меня возник план перенести ее на Радио-86РК. Напомню: 1.78MHz, 32Кб памяти, символьный экран 78x30 или 156x60 через псевдографику.

Для начала было интересно посмотреть, как могло бы выглядеть изображения на экране РК. Например, вот так (не могу понять почему, но надо нажать CTRL-R или F5 после перехода по ссылке, а иначе только черный экран).

В принципе, красиво, я решил продолжить. Взяв за основу исходник Вячеслава, я добавил туда вывод в стиле РК символами псевдографики - 178x60. Выглядит неплохо.

Итак, идея работает. Надо думать, как это все потенциально писать на 8-битном ассемблере Intel 8080, где даже деления нет. Надо переводить все в целые числа, а синус брать по таблице. Реализация с вещественными числами немного поменялась, стала использовать табличный синус. Несмотря на использование только 128 целых значений синуса на всем интервале от 0 до 2*PI, к тому же теперь домноженных на 256 и округленных в целое, выглядело тоже неплохо (случайно вышел забавный эффект в начале демки, когда буквы приезжают сзади).

Дальше надо было уже убирать библиотеку Processing.js, все переводить на целые и желательно положительные числа. Для целочисленности я все домножил на 256, а для положительности ввел смещение. Исходник уже становился все хуже и хуже, но все еще работал. Я везде по возможности упрощал константы и вставил проверки на положительность переменных.

И вот родилась первая версия на ассемблере, где можно было считать синус. В качестве эксперимента я попробовал рисовать синусоиду.

Очевидно, что с такой производительностью полный кадр 156x60 она будет считать полгода. Первый облом.

Решил я перейти в разрешение 78x30, просто символы, без псевдографики. Сам исходник на JavaScript несильно поменялся, разве что константы. Выглядело тоже сносно.

Уже эту версию я полностью реализовал на ассемблере 8080. Получился монструозный опус почти на тысячу строк. А работал он вот так… Второй облом.

Он отступать уж совсем поздно было, и я предпринял последнюю, хоть уже немного “нечистую” попытку. С помощью генератора на С я записал все кадры вместе с разницей между соседними. Сам же плеер этого самопального MPEG’а был очень короткий.

В итоге - ОНО! (на эмуляторе в браузере)

И теперь уже на настоящем РК (почти настоящем):

Мораль

Уметь найти в себе силы признавать бесперспективность той или иной затей и вовремя остановиться.

P.S.

Исходники все этого мучения доступны - https://github.com/begoon/rk86-3d-demo/


Disclaimer

Комментарии