Doom engine («рушій Doom»), також відомий як id Tech 1 — псевдотривимірний гральний рушій, розроблений американською компанією id Software і застосовуваний у комп'ютерних іграх Doom, Heretic, Hexen, Strife, HacX та інших іграх, створених за ліцензією. Створений Джоном Кармаком, допоміжні функції були написані , Джоном Ромеро, і Полом Редеком (). Спочатку написаний на комп'ютерах NeXT, потім, для першого релізу Doom був портований під DOS, а пізніше ще на кілька ігрових консолей і операційних систем.
Відмінності від Wolfenstein 3D engine
Підлога і стеля можуть мати будь-яку висоту. Стіни не обов'язково орієнтовані у напрямку «північ-південь» або «захід-схід». Змінювана освітленість, що підвищує реалістичність графіки. Ліфти, двері, що дистанційно відчиняються, стелі, що опускаються і придушують, сходи, що піднімаються, та інші рухомі елементи. Персонажі можуть стрибати, падати з дахів і літати по повітрю (втім, пройти під ворогом, який летить, або пролетіти зверху в стрибку все одно неможливо). Звукова підсистема підтримувала стереозвук і до 8 ефектів одночасно. Персонаж під час руху погойдувався вгору-вниз, що створило більшу ілюзію ходьби (у Wolfenstein точка огляду перебувала на постійній висоті приблизно на рівні живота, гравець немов їхав у інвалідному візку). Дозволялося (хоч і не заохочувалося) підключення додаткових модулів (WAD-файлів) з рівнями, графікою і звуками. Ідея розширюваності пішла від Джона Кармака, який сам модифікував ігри і хотів, щоб інші це робили.
Обмеження
Лабіринт має горизонтальну підлогу зі стелею і вертикальні стіни. Дві кімнати не можуть знаходитися одна над іншою. Таким чином, карта рівня є абсолютно двовимірної. У всій грі масштаб спрайтів і текстур постійний. Тому, наприклад, неможливо встановити високодеталізований плакат на менш детальній стіні. Автори так і не пропрацювали вертикальні зіткнення об'єктів. Тому не можна, наприклад, пробігти під какодемоном, що летить, або, розігнавшись на якомусь даху, перестрибнути через факел. (Виправлено в Heretic і Hexen, оскільки в них це було необхідно через магічну можливість польоту гравця.) Гра не робила й інших перевірок по осі Z — наприклад, імп, що блукав у підвалі, цілком міг завдати пошкодження гравцеві, який знаходиться на декілька сотень метрів вище, на горищі, а ракета, що вибухнула біля основи будівлі, завдавала шкоди монстрові на даху. Гравець міг використовувати перемикачі незалежно від висоти (наприклад, все ще можна активувати зниклий під землею вимикач на рівні MAP01 Entryway в Doom 2). Особлива структура рівня (так зване бінарне розбиття простору) вимагала збирання перед випробуванням рівня. Збирання відбувається автоматично, на комп'ютерах того часу менш ніж за хвилину — проте, це заважало переглядати рівень в реальному часі прямо по ходу редагування (на відміну від Build Engine). До того ж двійкове розбиття ділило стіни на «відрізки» () — це ускладнювало геометрію рівня. Duke Nukem 3D версії 1.3 успішно працював на комп'ютерах класу Pentium-100 на роздільності 640×480 — жоден порт Doom не здатний на таке. Через це рух об'єктів можливий, але по горизонтальній площині рух обмежено, на відміну від Build Engine. Висота текстури, якщо та повторюється по вертикалі, повинна завжди дорівнювати 128 текселям. Для неповторюваних текстур (щаблів, ґрат і т. д.) це не потрібно. Виправлено в численних портах Doom. Перегляд вгору-вниз, реалізований в Heretic, був псевдотривимірним, вертикальні лінії завжди залишалися вертикальними.
Технічні особливості Рушій був написаний на Сі на робочих станціях NeXT в операційній системі NEXTSTEP. Спочатку використовувався компілятор Intel C, але в подальшому був використаний . Утиліти були написані під NeXT на Objective-C. Рушій Doom був прогресивним для свого часу. Незважаючи на те, що Сі — мова процедурного програмування, рушій Doom написаний в явно вираженому об'єктному стилі.
Будова рівнів
Всі рівні в Doom насправді двовимірні, що вказує на одне з обмежень рушія: неможливо мати кімнату (сектор) над іншою кімнатою. Однак, з іншого боку, це дозволяє без особливих проблем малювати карту рівня з відображенням всіх стін і об'єктів, на відміну від інших ігор цього жанру.
Рівень складається з десяти блоків .WAD-файла; з них п'ять (VERTEXES, LINEDEFS, SIDEDEFS, СЕКТОРІВ і THINGS) безпосередньо редагуються користувачем, ще п'ять (SEGS, SSECTORS, NODES, REJECT і BLOCKMAP) — обчислюються BSP-побудовником.
Рівні будуються за субтрактивним принципом: весь простір заповнений непрохідною матерією, і автор рівня «прорубує» в цій матерії тунелі. Основою рівня є вершини () — точки у плоскому просторі. Між вершинами проводяться відрізки (). Відрізок може мати одну або дві сторони (). Текстури задаються не для відрізків, а для сторін, так що відрізок може бути покритий з різних боків різними текстурами.
Вершини і відрізки утворюють плоский граф; кожна його грань може бути або непрохідним простором (наприклад, колоною), або сектором (). Іноді структуру секторів навмисно порушують — на цьому засновані спецефекти на зразок невидимих мостів. Кожен сектор має в плані довільну форму (не обов'язково опуклу або однозв'язну). У сектора завжди горизонтальні підлога зі стелею і постійна освітленість. Односторонні відрізки є глухими стінами, двосторонні — утворюють переходи між секторами.
Щоб забезпечити найвищу на той час інтерактивність, застосовані так звані теги. Відрізок і сектор мають особливе ціле поле — «тег». Щоб зробити вимикач, який опускає ліфт, відрізку-вимикачу задаються код дії «вимикач, опускає ліфт» і який-небудь тег (наприклад, 5). Цей тег присвоюється сектору-ліфта. При активації відрізок буде виконувати вказану дію на всіх секторах з цим тегом.
Нарешті, на рівні розставляються об'єкти (). При цьому набір характеристик об'єкта в Doom виявився досить бідний: наприклад, не було Z-координати, наземний об'єкт на початку гри завжди стояв на підлозі, а повітряний — висів під стелею. Не можна зробити, щоб об'єкт був тільки в одиночній грі, або тільки в deathmatch, або тільки в кооперативній (був лише прапор «тільки в мережевих іграх»).
Гра Всі обчислення проводяться з нерухомою комою 16,16, з машинною одиницею, що дорівнює одному текселю (зріст гравця 56 текселівСирцевий Doom Legacy 1.11, 1.12) — отже, 1 тексель приблизно дорівнює 3 см). Для кутових величин застосовується нерухома кома, в якій 232 = 360°. Втім, більшість кутових розрахунків були грубіші — наприклад, повороти гравця розраховуються з точністю до 360° = 216 = 65536, а тригонометрична таблиця складалася всього з 8192 (213) величин.
Запис демо-роликів і мережева гра засновані на тому, що на цифровій ЕОМ один і той самий код з однаковими даними призводить до одного і того ж результату, а поведінка цілочисельної арифметики жорстко специфікована і не залежить від моделі процесора. Гра записує демо-ролик (і передає по мережі) команди керування; якщо в грі немає грубих помилок, різні машини, інтерпретуючи одні й ті самі команди керування, отримують однаковий результат. Втім, помилки, що призводять до розсинхронізації, в грі все-таки є: зокрема, якщо в одиночній грі зайти в меню, гра зупиняється, але ролик продовжує писатися. Недолік такого підходу — неможливість перемотати ролик; його можна тільки програти з початку.
В режимі запису демо-роликів точність поворотів знижувалася до 256 на 360 градусів; уважний гравець може помітити, що в режимі демозапису наведення стає грубішим. Це служить виключно для економії пам'яті в демо-роликах.
Кожен ігровий такт (1/35 секунди) гра проводить цикл керування кожним монстром. Щоб заощадити процесорні такти, існує бітова матриця REJECT: для будь-яких двох секторів, якщо з жодної точки сектора А не видно ніяку точку сектора Б, на цьому місці в матриці ставиться одиниця. Якщо на перетині рядка, що відповідає сектору гравця, і стовпця, відповідного сектору монстра, стоїть 0, проводиться перевірка, чи бачить монстр гравця; якщо 1 — монстр гарантовано не бачить гравця. Матриця REJECT дуже складна для побудови, і більшість користувацьких редакторів заповнювали її нулями (існувало дуже мало утиліт, які будували її; основні — RMB і ZENNODE).
Структура BLOCKMAP застосовується фізичним рушієм, щоб прискорити перевірку зіткнень об'єктів з відрізками.
Побудова зображення Для прискорення відображення використовується BSP-дерево (на відміну від порталів в Duke Nukem 3D). Об'єкти зображуються у вигляді спрайтів, на відміну від Quake.
Рушій рекурсивно проходить по BSP-дереву, вимальовуючи стіни від ближніх до дальніх: функція ПрохідПоДереву(вузол)
якщо ОхоплювальнийПрямокутник(вузол) не в конусі видимості то вихід
якщо вузол є розвилкою
то // вузол є розвилкою - рекурсивно пройти якщо камера ліворуч від січної площини то ПрохідПоДереву(вузол.лівий); ПрохідПоДереву(вузол.правий) інакше ПрохідПоДереву(вузол.правий); ПрохідПоДереву(вузол.лівий)
інакше // вузол є підсектором намалювати(вузол)Тут і задіяні три блоки, що залишились. Сектори розбиваються січними на опуклі елементи, іменовані підсекторами (SSECTORS), відрізки — на сегменти (SEGS). Сама структура дерева (охоплювальні прямокутники, січні, вказівники на «синів») зберігається в блоці NODES. У цьому циклі малюються тільки глухі стіни (тобто, середні текстури для односторонніх стін, і верхні і нижні — для двосторонніх). Об'єкти, підлоги і решітки записуються в окремі масиви і вимальовуються на пізніших стадіях. Масив, у якому зберігаються підлоги, зроблений досить малим, і в самодіяльних конструкторів досить часто траплялося переповнення і вихід з повідомленням «No more visplanes!».
Після того, як вималювано стіни, порядково малюються підлоги, записані у visplanes.
В кожному секторі тримається зв'язаний список об'єктів, які знаходяться в ньому. На етапі вимальовування стін видимі об'єкти разом з точками відсічення складаються в масив. Після того, як рушій намалює підлоги і стелі, масив сортується, і найближчі 128 об'єктів малюються від далеких до ближніх з допомогою тих самих процедур, що використовуються для малювання стін. На цьому ж етапі малюються і решітки («середні» текстури на двосторонніх стінах).
Текстури стін і спрайт зберігаються .WAD-файлі за стовпцями, текстури підлоги і стелі — простий масив 64×64.
Doom для DOS працював у режимі VGA 320×200 з потрійною буферизацією, для Linux — використовував звичайний режим VGA 13h. При цьому величина роздільності була закодована в асемблерних процедурах у двох місцях; версії гри, які використовували змінну роздільність, або мали кілька функцій під різні роздільностіСирцевий текст Smack My Marine Up, або динамічно модифікували код, підставляючи потрібну роздільністьСирцевий текст будь-якої версії Doom Legacy для DOS, функція ASM_PatchRowBytes.. Втім, у частинах гри, які до рушія не відносяться, зустрічалося вкрай багато магічних чисел, пов'язаних з роздільністю екрану і екранними координатами різних об'єктів, тому перші порти Doom страждали «розповзанням» графіки меню в SVGA-режимахНаприклад, Doom Legacy 1.11, 1.12.
Тривале завантаження Doom відомий своїм тривалим завантаженням (більше хвилини на комп'ютерах свого часу). Основна частина часу витрачалася на ініціалізацію «демона перемальовування Doom» ().
Doom поширювався на дискетах і через BBS, тому важливим був кожен байт. Щоб зменшити розмір, зробили такий механізм. Кожна з текстур для стін складалася з фрагментів (): наприклад, стіна з вимикачем може складатися з картинки стіни і картинки вимикача, або плиткова стіна — з трьох-чотирьох плиток, хаотично розкиданих по великій текстурою. Текстури, як сказано вище, малюються по стовпцях. Doom проходився по всіх стовпцях всіх текстур і перевіряв, які фрагменти покривають той чи інший стовпець; будувалася відповідна структура даних. Цю структуру можна було закешувати, або будувати при завантаженні рівня, добудовуючи динамічно в міру потреби — в цьому випадку Doom завантажувався б набагато швидшеТак чинять у багатьох портах Doom — зокрема, Doom Legacy і Smack My Marine Up; сирцеві тексти обох вільно доступні..