Blend4Web NPM пакет

Ни для кого не секрет, что наиболее востребованным направлением разработки на рынке труда является разработка приложений так или иначе связанных с Интернет. Это всевозможные новостные и развлекательные сайты, торговые площадки, социальные сети, CRM-системы, различного рода сервисы, онлайн игры итд. С каждым днем появляется все больше и больше новейших технологий, о которых вчера мы рассуждали скептически, а сейчас широко используем. А чтобы получить доступ к этим технологиям нам нужно всего лишь установить веб-браузер. К такой технологии в том числе относится и WebGL, о которой, я думаю, мы еще поговорим. А для начала, самую малость, окунемся в историю.

Дисклеймер
Данная статья является уроком для новичков с разъяснением "на пальцах". Поэтому опытные программисты вряд ли найдут для себя в ней что-то новое.


Итак, что же такое NPM и откуда он появился?

Сначала ничего не было (о_О)


Потом появился Chrome - веб-браузер от компании Google, на текущий момент являющийся самым популярным браузером в мире.


Затем появился NodeJS, основой которого стал движок V8 из Chrome. NodeJS по своей сути является средой выполнения JavaScript-программ, которая превратила язык JavaScript из чисто браузерного в язык общего назначения. А наибольшую популярность NodeJS приобрел в сфере разработки серверных приложений.


Далее умные программисты создали наимощнейшую инфраструктуру для разработки приложений на JavaScript - пакетный менеджер NPM, назначением которого является установка  используемых JavaScript-программой библиотек и их зависимостей.


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

Спешу порадовать тебя, мой юный друг! Теперь в недрах NPM ты можешь найти и Blend4Web!

Правда и искать то его не нужно... Но все попорядку.

Установка NodeJS

Способов установки NodeJS на различные операционные системы несколько. Мы рассмотрим способ, который автор считает наиболее приемлемым, так как он минимизирует вероятность возникновения каких-либо проблем в процессе разработки.
Суть этого способа в том, чтобы отказаться от установки NodeJS через инсталляционные пакеты (будь то .msi на Windows, .pkg на MacOS, .deb, .rpm итд на Linux), а вместо этого использовать другой тип дистрибутива. Возможно, что вам в вашей работе могут понадобиться различные версии NodeJS и если использовать инсталляционные пакеты, то держать их на одной операционной системе может быть проблематично, либо вовсе не возможно.

Качать NodeJS мы будем конечно же с официального сайта. Из доступных вариантов скачивания нас интересуют дистрибутивы для соответствующих операционных систем, помеченные как Binaries: Linux Binaries (x86/x64), Windows Binary (.zip), macOS Binaries (.tar.gz).
Скачав дистрибутив для нашей операционной системы, мы понимаем, что это всего лишь архив, который нужно куда-нибудь распаковать и сделать исполняемые файлы node и npm доступными из командной строки. Другими словами после распаковки необходимо настроить окружение (environment). Для этого во всех операционных системах существует переменная окружения PATH, которую необходимо дополнить путем к директории с исполняемыми файлами.

Для Linux и MacOS настройка окружения осуществляется одинаково.
Для настройки окружения я рекомендую использовать файл ~/.profile, поскольку он является с одной стороны локальной пользовательской настройкой, с другой стороны инициализирует окружение в том числе для графических утилит (в отличие например от файла конфигурации ~/.bashrc).
Итак, в конец ~/.profile добавляем строчку
PATH=/home/user/path/to/node/binaries:$PATH
Т.к. командный интерпретатор (в моем случае bash) вызывает первую найденную программу в процессе последовательного обхода путей из PATH, то путь мы добавляем именно в начало, перед содержимым переменной PATH, чтобы никакие другие программы с именами node или npm не встретились раньше чем те, которые мы в данный момент устанавливаем. У меня эта строчка выглядит так:
PATH=/home/dal/soft/node-v8.8.1-linux-x64/bin/:$PATH
Перезаходим в операционную систему и запускаем терминал. Проверяем, что node и npm доступны
Начиная с этого момента я буду использовать команды *nix-систем. Пользователи Windows должны добавлять расширение .exe, например node.exe или npm.exe.
node --version
npm --version

Если терминал сообщил вам, что программа не найдена, значит вы где-то совершили ошибку. Используйте команду env (в *nix-системах), чтобы вывести все переменные окружения. Найдите там PATH и проверьте вручную доступность исполняемых файлов по указанному пути.

env | grep ^PATH=

Как настроить переменные окружения для Windows можно посмотреть например тут.
NodeJS установлен и это все, что нам необходимо! Поэтому..

Приступим к работе

  1. Создайте где-нибудь в директории со своими проектами новую директорию, например b4w_test.
  2. Перейдите в нее и создайте новый пакет (в некотором роде проект в терминах npm):
    cd b4w_test
    npm init
    
    Эта команда задаст вам несколько вопросов. Вы не обязаны отвечать на них, а можете просто жать Enter.
    После выполнения команды вы найдете в текущем каталоге файл package.json. В любое время вы можете исправить свои неверные ответы команде npm init отредактировав этот файл.
  3. Теперь мы подходим к самому интересному:
    npm install blend4web
    Эта команда установит в директорию node_modules пакет blend4web.
  4. В описании пакета можно заметить информацию о том, что пакет содержит примеры приложений в директории projects. И в данный момент там находится один проект с названием my_project.
    А давайте попробуем его!
    1. Копируем все содержимое из node_modules/blend4web/projects/my_project/ в наш проект b4w_npm_test (обратите внимание, что в таком случае package.json перезапишется).
    2. Устанавливаем все зависимости скопированного приложения:
      npm install
    3. Запускаем скрипт start из package.json:
      npm run start
      Скрипт запускает сборщик webpack в режиме watch и webpack-dev-server, а также открывает наше приложение в браузере.

      Далее вы можете изменять код приложения и проверять результат своих модификаций, обновляя страничку, как вы привыкли это делать. Сборщик webpack автоматически распознает измененные файлы и произведет необходимые действия по сборке.
      Чтобы остановить сервер, в окне консоли с запущенной командой "npm run start" нажмите Ctrl+C

А давайте попробуем сделать что-нибудь с нуля?

А что бы такое сделать?...
Поиграв с кристаллами из предыдущего приложения, я заметил, что пользователь может взаимодействовать с кристаллами, а вот кристаллы друг с другом не могут. И мне захотелось сделать приложение, в котором объекты взаимодействовали бы друг с другом физически.

Итак, начнем с того, что мы уже делали - создадим новый пакет с именем b4w_npm_test (пункт 1-3 из раздела "Приступим к работе").
Чтобы создать сцену нам необходим Blender с установленным аддоном Blend4Web. Допускаю, что с Blender вы в какой-то степени знакомы, и устанавливать аддоны вы умеете, а если нет, то у вас не возникнет трудностей прогуглить этот вопрос. Как я уже говорил, npm-пакет содержит все необходимое для создания своих собственных приложений, в том числе и аддон, который вы можете найти в директории dist/addons/.

После установки аддона в хэдере 3DView у рендеров Cycles и Blend4Web появится кнопка "Fast Preview".


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

Уже сейчас вы можете поэкспериментировать c экспортом любых моделей и посмотреть что выходит. Если что-то выходит не так, как вы ожидаете, то возможно данная фича еще не реализована, либо вы нашли баг. Если вы столкнулись с какими-либо сложностями, непременно оставляйте отзыв на официальном форуме Blend4Web, так вы поможете сделать Blend4Web еще лучше!

Сцена с нуля

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

На вкладке Physics я включил галочку "Object Physics", выставил "Physics Type" в "Rigid Body", Установил галочку "Collision Bounds" с оставленным по-умолчанию значением Box для поля Bounds. Помимо этого, чтобы кубик не засыпал при низких значениях скоростей, я установил галочку "No Sleeping". Эта галочка позволит получить симуляцию падения моей башни.

Если нажать кнопку Fast Preview, то мы увидим падение нашего кубика вниз, ведь он теперь динамический и на него действует гравитация. Давайте сохраним наш blend-файл. Я разместил его в поддиректории проекта с именем blender и назвал его main.blend.

Моя башня будет стоять на полу, который я сделаю из объекта Plane. Объекты я разместил так, чтобы кубик не пересекался с Plane. Для Plane На вкладке Physics я просто включил галочку "Object Physics", а необходимый нам тип физического объекта Static уже выставлен по-умолчанию. Теперь кубик уверенно стоит на полу и никуда не падает.

Башню я сформирую прямо в Blender. Для этого я продублирую наш кубик несколько раз следующим образом:
  1. Выбираем самый верхний кубик и дублируем его. Shift+D, Enter
  2. Смещаем кубик на самый верх. G, Z, 2, Enter
Теперь я сдвину самый нижний кубик куда-нибудь в плоскости пола, чтобы создать неустойчивое состояние для башни, в котором она начнет падать. И вот как это выглядит у меня:


Вроде все работает, но если вращать колесико мышки, то наша сцена куда-то пропадает при отдалении. Для этого поменяем настройки Clipping камеры.
Теперь нам нужно экспортировать нашу сцену. Для этого в Blender выбираем File->Export->Blend4Web(.json) и сохраняем экспортированную сцену в поддиректории assets нашего проекта. Мы получаем два файла, это main.json и main.bin. Файл main.json содержит метаданные экспортированных сцен, а bin - данные вершин, текстурные координаты и другие атрибуты, в общем все, что связано с мешами моделей. Но что нам делать дальше с этими файлами?
Мы будем писать свое собственное приложение.

Перейдем к программированию

Вы уже могли слышать что Blend4Web начиная с версии 17.12 ввел поддержку модулей ES6. В двух словах, это методика подключения библиотек, используя которую вы не обязаны явным образом при помощи тегов script включать все ее зависимости в html-файл, а они будут подключены автоматически. Более того, данная система позволяет уменьшить код результирующего приложения путем отбрасывания неиспользуемых функций подключаемых библиотек. Однако для того, чтобы ES6 модули работали корректно, в большинстве случаев необходимо использовать сборщики модулей.
Рассмотренный пример, поставляемый в npm-пакете написан с использованием ES6 и использует Webpack для сборки модулей. Замечу, что если вы использовали какие-либо конструкции ES6, помимо import/export (ключевые слова для ES6-модулей), то для того, чтобы ваш код работал во всех браузерах, вам может потребоваться сконвертировать его в ES5, например средствами babel. О сборщиках мы поговорим в следующий раз, а сейчас я опишу 100% работающий для всех современных браузеров подход: мы будем использовать уже собранную библиотеку blend4web, которая имеет нотацию ES5.

Собранные библиотеки находятся в директории dist. Это любой из файлов b4w.js, b4w.min.js, b4w.simple.min.js, b4w.whitespace.min.js. Отличие их лишь в уровне обфускации.
Чтобы открыть наше приложение я воспользуюсь статическим сервером, который я установил командой "npm install node-static" и запускаю в каталоге с проектом командой "static". По адресу http://127.0.0.1:8080/index.html я могу найти свое приложение. Приведу здесь листинги основных файлов приложения с комментариями, которые вы можете использовать в своих проектах.

Итак - index.html:
<html>
  <head>
    <title>Blend4web Test</title>
    <!--Собранный движок-->
    <script src="b4w.min.js" type="text/javascript"></script>
    <!--Наш код-->
    <script src="b4w_npm_test.js" type="text/javascript"></script>
  </head>
  <body style="background-color: black;">
    <div id="main_canvas_container" style="height: 100%; left: 0px; position: absolute; top: 0px; width: 100%;"></div></body>
</html>

А вот и основной код приложения b4w_npm_test.js:

"use strict"

b4w.register("b4w_npm_test", function(exports, require) {
// импортируем необходимые модули
var m_app       = b4w.require("app");
var m_cfg       = b4w.require("config");
var m_data      = b4w.require("data");
var m_preloader = b4w.require("preloader");

var DEBUG = true;

// задаем путь к ассетам
var APP_ASSETS_PATH = "assets/";
// задаем путь к физическому движку
m_cfg.set("physics_uranium_path", "node_modules/blend4web/dist/uranium/")

/**
 * экспотрируем метод инициализации, который будет вызван в самом конце файла
 */
exports.init = init;
function init() {
    m_app.init({
        canvas_container_id: "main_canvas_container",
        callback: init_cb,
        show_fps: DEBUG,
        console_verbose: DEBUG,
        autoresize: true
    });
}

/**
 * коллбэк вызывается когда приложение инициализировалось
 */
function init_cb(canvas_elem, success) {

    if (!success) {
        console.log("b4w init failure");
        return;
    }

    m_preloader.create_preloader();

    // игнорируем клик правой кнопкой мыши на элементе canvas
    canvas_elem.oncontextmenu = function(e) {
        e.preventDefault();
        e.stopPropagation();
        return false;
    };

    load();
}

/**
 * загрузка данных сцены
 */
function load() {
    m_data.load(APP_ASSETS_PATH + "main.json", load_cb, preloader_cb);
}

/**
 * обновление прелоадера
 */
function preloader_cb(percentage) {
    m_preloader.update_preloader(percentage);
}

/**
 * коллбэк вызывается когда сцена загружена
 */
function load_cb(data_id, success) {

    if (!success) {
        console.log("b4w load failure");
        return;
    }

    m_app.enable_camera_controls();

    // размещайте свой код здесь
}
})

b4w.require("b4w_npm_test").init();


На сегодня все! Надеюсь эта статья была полезна не только новичкам! По ссылкам ниже вы сможете найти исходники приложения а так же нас в социальных сетях. Всем удачи и интересных проектов!


Полезные ссылки:
Запустить приложение
Исходный код приложения

Документация Blend4Web
Документация разработчика Blend4web

Tвиттер автора статьи

Твиттер Blend4web
Фейсбук Blend4web
ВК Blend4web

Blend4Web NPM пакет