В течение прошлого месяца я работал над реализацией поддержки азиатских языков. Добавление поддержки китайского было одним из самых популярных запросов после релиза в Steam! Основная проблема заключалась в том, что SpaceEngine внутренне использовал 8-битные текстовые строки, поэтому он мог поддерживать только кодировку ANSI для текста на разных языках. Это приводило к ограничению в 256 символов (даже меньше, поскольку некоторые коды зарезервированы, а цифры и английские буквы также зарезервированы и не могут быть изменены на национальные символы). Это явно слишком мало для китайского языка: текущая реализация использует около 1300 иероглифов. Так что была необходима поддержка юникода. Юникод – это набор схем кодирования символов, одна из которых представляет собой 16-битные текстовые строки (используются внутренне в Windows). 16-битные строки могут поддерживать до 65536 символов – достаточно для китайского!

Другая проблема заключалась в том, что SpaceEngine использовал текстурные шрифты, по три текстуры на каждую кодовую страницу ANSI (маленький шрифт, маленький с тенями, и большой). Рисовать текстуру шрифта вручную для китайского языка было бы адом, поэтому первое, что я сделал, это реализовал рендеринг TTF шрифтов. TTF – это векторный формат шрифта, используемый практически во всех операционных системах для рисования текста. Файлы TTF, описывающие тысячи азиатских символов, очень маленькие, всего несколько мегабайт. С библиотекой freetype для C ++ работать со шрифтами TTF очень легко: она имеет функцию для рисования запрошенного символа с указанным размером в буфер памяти. Затем этот буфер можно скопировать в текстуру OpenGL для использования в движке. Для более оптимального рендеринга лучше использовать одну общую текстуру для всех символов, поэтому я реализовал простой алгоритм заполнения текстурного атласа, с возможностью увеличить текстуру, если свободное пространство в ней закончилось. То есть если нужный символ отсутствует в текстуре, SE просто добавляет его туда. Так что теперь SE может отображать все языки одновременно.

Я также избавился от разных текстур для разных размеров шрифта: все глифы рисуются в одну и ту же текстуру. Эффект тени (который делает текст лучше читаемым на ярком фоне) легко добавляется шейдером рендеринга шрифтов.

Пример сгенерированной текстуры шрифта для китайского языка:

Сравните его со шрифтом, сгенерированным для английского языка (все европейские языки могут легко поместиться в эту текстуру 512*512, включая все размеры шрифтов):

На этом лёгкая часть закончилась. Мне предстояло обновить почти все файлы исходного кода, заменив 8-битные строки на 16-битные для поддержки 16-битного юникода (UTF-16). Это не так просто, как могло бы показаться на первый взгляд: тупо «найти и заменить все» не сработало бы. Некоторые структуры данных по-прежнему должны были использовать 8-битные строки и 8-битные поля данных (тип данных char в C/C++). Это была долгая и нудная ручная работа, занявшая 4-5 дней. А после окончания я преобразовал файлы локализаций SE в юникод (UTF-8) и начал отладку, что заняло еще 2 недели.

Я также обновил меню выбора языка: теперь оно отображает флаг страны и самоназвание (автоним) языка (см. скриншот в начале этого поста). При первом запуске после обновления SpaceEngine должен автоматически сменить язык на тот, который установлен в вашем клиенте Steam.

Сегодня я выпустил билд 0.990.37.1690 в ветку beta. Он включает в себя локализации на традиционный и упрощенный китайский языки, сделанные “xingqiu” и “Lidi” (“Freeman”), и на японский язык, сделанный “Luna Knowledge” (“alpha0106” со старого форума) в 2015 году и обновленную сейчас. Да, многовато времени мне потребовалось, чтобы реализовать поддержку юникода!

Список изменений в этой сборке:

Build 0.990.37.1690

  • При экспорте текстур планет прозрачность облаков не сохраняется в отдельном файле
  • Возможность указать пользовательскую подпапку для сохранения видеофайла/кадров в диалоге захвата видео
  • Исправлена ​​ошибка, из-за которой не генерировались некоторые текстуры нодов ландшафта
  • Исправлена ​​ошибка, из-за которой ландшафт не генерировался во время записи видео
  • Эффект оппозиции на кольцах планет; параметры для управления им добавлены в скрипты планет и редактор
  • Поддержка юникода:
    – Все локализации преобразованы в кодировку UTF-8
    – Текстурные шрифты заменены на TTF-шрифты
    – Добавлены локализации: традиционный китайский, упрощенный китайский и японский
    – В меню выбора языка отображаются флаги стран и самоназвания языков
  • Модель Лунного модуля Аполлона-11 «Орёл» на поверхности Луны
  • Исправлена ​​ошибка, из-за которой окно интерфейса застревало в режиме перемещения, если оно было закрыто горячей клавишей до отпускания левой кнопки мыши
  • Исправлено выделение звёзд в звёздных скоплениях и туманностях
  • Щелчок мыши в поле ввода текста перемещает курсор к ближайшему символу
  • Исправлена ​​работа кнопок со стрелками на слайдерах разрешения рендеринга объёмных объектов
  • Я также обновил руководство по созданию локализаций, на случай, если кто-то захочет добавить перевод на свой язык, или обновить устаревшие локализации, которые были в SE 0.980, но были исключены из 0.990. Среди них: венгерский, индонезийский, норвежский, европейский португальский, бразильский португальский, румынский, словацкий и турецкий.

    Upd: обновление выпущено 1 августа.

    Обсудить этот пост на форуме.