Info Guide #11
05 июля 2015

Code - точка зрения: проекция пространства на экран из одной точки.

        Точка зрения
Alone Coder 

  Не совсем очевидно,но проекция простра─
нства  на  экран  из одной точки ничего не
говорит  о расстояниях, сколько  бы  мы ни
крутились-вертелись в разные стороны. Поэ─
тому такие проекции строить гораздо легче,
чем настоящее 3D,и этим можно пользоваться
и в играх ( Myst III: Exileи т.п.). 

                  * * *

   Рассмотрим простейший случай - пусть мы
(камера) стоим  в одной точке и крутим го─
ловой  только  в стороны. У нас всего одна
степень свободы. Что мы видим?
   Мы  видим  то  же самое, как если бы мы
стояли  в середине цилиндра с натянутой на
нём текстурой. Или то же самое,как если бы
мы стояли в середине куба. Или призмы. Это
не имеет значения.

   Цилиндр проще всего в реализации,потому
что  он  позволяет при любом угле поворота
пересчитывать  экранные координаты в коор─
динаты  в текстуре простым лукапом по таб─
лице (это будет большая таблица - для каж─
дого пикселя). Он также позволяет и другой
метод - при любом угле поворота используем
одну  и ту же таблицу, хранящую смещение в
текстуре  и  масштаб  для каждого столбца.
(Столбы масштабируем как в Wolfenstein .)
   Этот  второй метод отнимает значительно
меньше  памяти и реально применим. Сначала
предполагалось  использовать его для трёх─
мерного квеста Big L, но при его разработ─
ке встал ряд трудностей, и этот код вместе
с  графикой  в  конце  концов попал в демо
New Wave 48K. 



   48К - это  достаточно сильное ограниче─
ние. Размер  текстуры  пришлось ограничить
512x128 (32 килобайта), потому что для ка─
ждого  столбца  (путём  экспериментов были
выбраны  столбцы  шириной  4 пикселя) надо
иметь  4  разных  сдвига в текстуре (чтобы
иметь шаг в 2 пикселя).
   Пояснение  про  размер текстуры: суть в
том, что руками сдвигать данные по горизо─
нтали медленно, поэтому надо хранить сдви─
нутые байты.Если сдвигать с шагом в 2 пик─
селя (а иначе как сохранить штриховку?),то
будет  4  сдвига. Мы не храним 2 сдвинутых
копии в одном  байте (их  было бы медленно
вдвигать  и  накладывать), а  только одну.
Поэтому при ширине512 получается (512/8)*
*4(сдвигов)*hgt байтов, что при  hgt=128 
даёт64*4*128=32768.

   Можно представить эту проекцию на рису─
нке (вид сверху):

   (где-то вдали - поверхность цилиндра)

             условный экран



                 камера,
         она же центр цилиндра

   Формулы были такие:

   Для  каждого n=-23.5..+23.5  с шагом 1
(это  номер  столбца)  считаемx=n/24 (это
номер  столбца в пределах-1..+1 ) считаем
уголa=arctg x (здесь угол зрения равен 90
градусов,иначе надо другие пределы дляx -
лучше меньше,но тогда нужно большее разре─
шение текстуры по горизонтали);
   считаем масштабk=cos a (можно добавить
коэффициент, если  хотим сэкономить на вы─
соте текстуры или наоборот сделать тексту─
ру точнее);
   считаем  координату  столбца в текстуре
xtex=a*128/pi (получается -32..+32  - для 
ширины 512 с шагом в 2 пикселя).

   Код использовался такой:

ld d,h
ld a,(de)
exx
xor (hl)
and d ;#f0
xor (hl)
ld (bc),a
inc h
inc b
exx
inc d

ld a,(de)
exx
xor (hl)
and d ;#f0
xor (hl)
ld (bc),a
inc b
[ld a,c:add a,20:ld c,a...между знакомест]
ex af,af'
add a,e
jr nc,$+3
inc h
ex af,af'
exx
add hl,bc

   Такое  рисование по 2 строчки приемлемо
из-за  небольшого  разброса масштабов. Оно
мало  того что ускоряет отрисовку, оно ещё
и позволяет  меньше  портить  штриховки на
картинке.
   Это был один из этапов борьбы за чисто─
ту картинки. Другой был связан с проблемой
растягивания по горизонтали (из-за малень─
кого разрешения  текстуры). Если  оставить
всё  как есть, то вертикальные линии будут
дублироваться. Чтобы  частично скрыть этот
дефект на имевшейся прорисованной картинке
(от Surfin' Bird ), сдвинутые копии столб─
цов  (те самые, которые шириной 4 пикселя)
редактировались следующим образом:
   на левой границе столбца (смотрим полу─
байты попарно):
01?? -> 10??
01?? -> 01??
   на правой границе столбца:
??10 -> ??10
??10 -> ??01
   Можно  сделать  и  наоборот (для других
картинок).

                  * * *

  Теперь  выйдем в новое измерение и поду─
маем насчёт подъёма-опускания камеры.Здесь
мы  опять  стоим  перед выбором - на какую
фигуру натянуть текстуру: цилиндр, куб или
другой  многогранник, сфера... И выбор тут
гораздо труднее.
   Если мы возьмём многогранник,нам придё─
тся озаботиться насчёт настоящего 3D-движ─
ка сtexture mapping (tmap), что сводит на
нет выигрыш от неподвижной камеры (хотя...
модель мира проще).
   Если цилиндр - то чем затыкать его кон─
цы? Если не затыкать,то нам нужна бесконе─
чная текстура.Или придётся ограничить углы
подъёма-опускания  камеры  (зенит  и надир
сделать невидимыми).
   Если  сфера - формулы пересчёта на каж─
дый пиксель просто ужасны.

   Можно  рассчитывать  только  узлы сетки
8x8, а между ними проводить интерполяцию -
упрощённый tmap. Этот метод проверен вре─
менем,и с ним можно использовать медленные
способы расчёта, такие как:

 1.Raymarching - сканирование воксельно─
го  объёма  с помощью маленьких шагов. Это 
уже было описано в статье"О летающем сло─
не"  в  Info Guide #10  (по поводу интры к
#5 ). Это очень медленный метод. 
 2.Настоящий расчёт проекции цилиндра на
экран. Для каждой точки считаем арктангенс 
и всё такое. 
 3.То  же, что п. 2, но  избавляемся  от
арктангенса, делая цилиндр квадратным. 

   Насколько мне известно,такие мудрёности
на  Спектруме  делал только SaiR00s в деме
Dogma, и  получилось  весьма медленно даже 
для того разрешения. Код не смотрел,но ри─
сковать не стал. В Nedodemo я выбрал самый
простой  метод, и  не зря - оказалось, что
даже  он едва-едва  успевал  на  тогдашней
компо-машине Pentagon 1024SL v2.2.
   Самый простой метод такой - для каждого
угла  подъёма  камеры  имеем свою таблицу.
Отрисовку  на экран производим непосредст─
венно  по  ней. Более  того, генерируем из
неё код (ld a,(hl):ld (de),a:inc d с нуж─
нымиinc/dec для h и l ). Проецировать мо─
жем на любую фигуру с осевой симметрией. Я
выбрал сферу.
   Текстуры были рассчитаны на куб (сдела─
ны через 3D-модель с 6 камерами), я перес─
читал их на сферу с помощью специально на─
писанной утилиты. Вы можете её найти в ис─
ходниках Nedodemo у меня на сайте.

   Казалось бы, забили 27 страниц памяти -
куда  так? Но  если не генерировать код из
таблицы, то  можно  заметить, что  таблицы
зеркально симметричны поX и попарно соот─
ветствуют  друг другу поY (с отражением).
Если  бы стояла задача загнать этот эффект
в128К, она была бы выполнена. А вот в 48К
- нет.48К  мир  существенно отличается от
мира расширенной памяти.
   Другой вопрос, что делать,чтобы поднять
разрешение  этого эффекта до приемлемого в
играх. К  сожалению, ответа  пока нет. Что
однозначно - текстура  должна иметь разре─
шение, превышающее  размер экрана не менее
чем  в 4 раза. В Nedodemo разрешение текс─
туры 256x64 (она немного сплющена по вер─
тикали) при разрешении экрана56x61, и те─
ксели  при  этом видны. То есть, например,
для  разрешения экрана256x128 понадобится
сферическая  текстура порядка1024x256 или
куб с текстурами256x256.




Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
WANTED - Розыск программ.
Улыбнитесь - Штиpлиц сидел в кaбинете...
Бук - Светлые пpоблемы темной головы.

В этот день...   19 ноября