Статьи

Создайте виртуальную реальность в виртуальной реальности с помощью Primrose и WebVR

Виртуальная реальность действительно набирает обороты в этом году, продавая виртуальные гарнитуры повсюду. Разработка виртуальной реальности неуклонно привлекает все больше внимания со стороны платформ разработки, поскольку они начинают обслуживать этих нетерпеливых разработчиков. Одной из самых интересных функций, представляемых Unity и Unreal Engine, является возможность редактирования сцен виртуальной реальности в виртуальной реальности. Разработчики, работающие с WebVR и JavaScript, будут рады узнать, что для них также существует платформа, которая предоставляет эту возможность для прототипирования и экспериментов WebVR — Primrose.

Что такое первоцвет?

Первоцвет лучше всего описан на их официальном сайте ,

Primrose — это кросс-браузерная многопользовательская среда для создания инструментов повышения производительности в приложениях WebVR.

Primrose предоставляет разработчикам прекрасную основу для открытия в браузере, экспериментирования с новыми идеями и изучения того, как они выглядят в виртуальной реальности. Это открытый исходный код, все еще очень новый и в активной разработке.

Что вам нужно

Чтобы продолжить и начать свое путешествие в мастерство WebVR с помощью Primrose, вам потребуется:

  • Браузер с поддержкой WebGL, предпочтительно с поддержкой WebVR, такой как последняя сборка Chromium WebVR или Firefox Nightly .
  • Гарнитура Oculus Rift (возможно, и HTC Vive) или Google Cardboard — однако вы можете экспериментировать и работать в браузере без гарнитуры!
  • Какой-то веб-сервер — подойдет локальный веб-сервер, такой как WAMP / MAMP / статический сервер Node / статический сервер Python!
  • Возможность касания шрифта — вы не сможете видеть свою клавиатуру в виртуальной реальности!

Начиная

Вы можете попробовать полностью рабочую версию живого кодирования на веб-сайте Primrose (убедитесь, что вы посещаете его с помощью браузера с поддержкой WebGL, подобного упомянутому выше, в противном случае вы увидите только статический снимок экрана) .

Если вы хотите, чтобы ваша собственная копия работала локально, вы можете загрузить / клонировать последнюю версию вместе с ее примерами из репозитория Primrose GitHub.

Наша упрощенная версия на GitHub

Для этой статьи я собрал упрощенную версию демонстрации живого кодирования. Он использует тот же код, что и демонстрационная программа Primrose, только с ограниченной функциональностью, чтобы упростить процесс объяснения на ранней стадии. Чтобы следовать этой статье, отправляйтесь в репозиторий GitHub для этой версии.

Запуск нашей упрощенной версии

Чтобы запустить нашу упрощенную версию демонстрации живого кодирования, скопируйте ее на свой веб-сервер, а затем откройте это местоположение в браузере с поддержкой WebGL (например, http://localhost/primrose или даже просто http://localhost если вы поместите его в свой браузер. корневой каталог сервера.

Примечание: это не будет работать из вашей файловой системы! Если вы пытаетесь запустить его из file:///Users/yourname/primrose/index.html как file:///Users/yourname/primrose/index.html , он сломается, так как браузеры не будут file:///Users/yourname/primrose/index.html JavaScript для доступа к файлам текстуры и тому подобное.

При этом вы должны увидеть что-то похожее на это:

Наше начальное демо

Если вы посмотрите вокруг в этой сцене, вы увидите готовый и ожидающий вас редактор кода. Вы можете навести курсор на строки в коде, щелкнуть, чтобы поместить туда курсор, а затем набрать его, как в обычном текстовом редакторе. Если мы щелкнем сразу после 10 в for (var i = 0; i < 10; i++) и изменим его на for (var i = 0; i < 100; i++) следующим образом:

Обновление нашего кода в нашей демоверсии

Наша сцена изменится в режиме реального времени, и теперь в ней будут случайно перемещаться 100 блоков!

Наше демо с 100 блоками

Если вы хотите лучше взглянуть на него с разных сторон, вы можете посмотреть на пол и щелкнуть туда, куда вы хотите перейти:

Двигаясь вокруг нашей демонстрации

Вы также можете использовать клавиатуру для перемещения по сцене, используя клавиши со стрелками.

Как это устроено

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

Запуск нашего приложения Primrose выглядит так:

 var BRICK = "images/brick.png", GROUND = "images/deck.png", SKY = "images/bg2.jpg", app = new Primrose.BrowserEnvironment("Our Simplified 3D Editor", { skyTexture: SKY, groundTexture: GROUND }), 

Эти строки кода определяют наши три файла текстуры, а затем создают наше приложение Primrose внутри переменной app . Метод Primrose.BrowserEnvironment() устанавливает нашу сцену с текстурами неба и земли.

У нас также есть переменная editorFrame которая устанавливает область 2048 на 2048 для нашего редактора, который будет помещен внутри:

 editorFrame = new Primrose.Surface({ bounds: new Primrose.Text.Rectangle(0, 0, 2048, 2048) }); 

Другим общим аспектом всех приложений Primrose (и многих других JavaScript-фреймворков в этом отношении) является инициализация наших элементов в addEventListener("ready", function() {}); , Здесь мы добавляем:

  • subScene — Что мы сможем добавить и изменить элементы внутри нашего редактора кода.
  • editor — наш живой редактор кода на нашей сцене (мы рассмотрим это чуть более подробно ниже!) .
  • Исходный код из getSourceCode() — в моей упрощенной версии он получает бит по умолчанию, который поставляется с редактором Primrose и отображается в нашем текстовом редакторе VR. В гораздо более сложном редакторе Primrose он может сделать немного больше с локальным хранилищем.
 app.addEventListener("ready", function() { app.scene.add(subScene); editor = new Primrose.Text.Controls.TextBox({ bounds: new Primrose.Text.Rectangle( 0, 0, editorFrame.surfaceWidth, Math.floor(editorFrame.surfaceHeight) ), tokenizer: Primrose.Text.Grammars.JavaScript, value: getSourceCode(isInIFrame), fontSize: 45 }); editorFrame.appendChild(editor); }); 

Primrose недавно выпустила новую версию, в которой редактор был обновлен с помощью ряда новых объектов инфраструктуры в Primrose.Text :

  • Primrose.Text.Controls.TextBox — устанавливает текстовую область и по умолчанию предоставляет весь спектр функций.
  • Primrose.Text.Rectangle — это позволяет нам определить прямоугольную границу для текстовой области, которая будет размещена внутри. Возможно, вы заметили это, когда мы определили наш editorFrame .
  • Primrose.Text.Grammars.JavaScript — используется в ключе tokenizer для настройки подсветки кода JavaScript. Вы можете сделать подсветку открытого текста через Primrose.Text.Grammars.PlainText .

При работе с приложениями Primrose есть несколько событий за пределами "ready" которые вы можете обратить внимание, в том числе:

  • "update" — это единственное другое событие, которое мы используем в примере кода редактора, оно запускается каждый кадр. Вы используете это в Primrose для запуска анимации и проверки обновлений в сцене.
  • "keydown" , "keyup" и "keypress" — запускается, когда клавиша нажата, отпущена, нажата и отпущена соответственно.
  • "mousedown" и "mouseup" — то же, что и выше, но с помощью мыши.
  • "mousemove" — обнаруживает движения мыши.
  • "wheel" — определяет, когда пользователь перемещает колесо прокрутки мыши.
  • "touchstart" , "touchend" и "touchmove" — обнаруживает, когда палец касается элемента в сцене с помощью сенсорного экрана, отрывает палец от экрана и соответственно проводит пальцем по экрану.
  • "unload" — запускается, когда приложение закрывается. Моя упрощенная версия редактора не использует это, однако полный редактор Primrose использует это для сохранения содержимого редактора в локальном хранилище.
  • "load" — запускается, когда приложение загружается еще раз.
  • "pointerstart" , "pointerend" и "pointermove" — реагирует на события нажатия и прикосновения к объектам, поэтому вам не нужно следить за обоими по отдельности.
  • "gazestart" — реагирует на тот момент, когда пользователь смотрит на объект.
  • "gazecomplete" — отвечает, когда пользователь смотрит на объект по умолчанию в течение одной секунды.
  • "gazecancel" — отвечает, когда пользователь отводит взгляд до истечения одной секунды по умолчанию. Вы можете изменить gazeLength значение по умолчанию через gazeLength но это выходит за рамки этой статьи.

Я не буду вставлять весь упрощенный код в эту статью (он будет довольно длинным и громоздким!). Вы можете проверить это в репозитории GitHub, указанном выше. Тем не менее, мы рассмотрим, что содержат некоторые ответы и функции на события.

В рамках события "update" нашего упрощенного приложения оно проверяет любые изменения кода в редакторе, обновляет их при каждом scriptUpdateTimeout (тайм-аут, который запускается каждые полсекунды) и запускает любые анимации, о которых оно уже знает.

Внутри ответа на события "keydown" он сбрасывает тайм-аут scriptUpdateTimeout , задерживая, когда наше приложение пытается что-то обновить!

Функция updateScript() запускается каждый раз, scriptUpdateTimeout завершается scriptUpdateTimeout . Это то, что проверяет, изменился ли скрипт нашего редактора, и заменяет работающий скрипт, если он видит обновление. Он очищает нашу subScene сверху и изменяет элементы в соответствии с кодом нашего редактора VR.

Функциональность кнопки настройки

Чтобы иметь возможность испытать правильное, захватывающее живое программирование (или любое другое приложение на основе Primrose, которое вы создали), мы хотим, чтобы оно могло работать в полноэкранном режиме. Это важно для VR, так как иначе работать не будет! Для этого мы добавляем кнопки для запуска этих режимов. Primrose имеет большую часть этого для нас, мы просто добавляем кнопку с идентификатором goVR и одну с goRegular , затем мы вызываем app.setFullScreenButton передавая имя идентификатора, что это событие click и либо true для VR, либо false для обычного полноэкранного режима:

 app.setFullScreenButton("goVR", "click", true); app.setFullScreenButton("goRegular", "click", false); 

Создание магии первоцвета

В настоящее время у нас есть различные кубы, перемещающиеся и изменяющиеся в реальном времени, когда мы корректируем наш код — но что еще мы можем построить в Primrose? Вот несколько элементов, которые вы можете добавить в testDemo() в вашем app.js или в вашу сцену в реальном времени!

Ось

Ось предоставляет вам набор красных, зеленых и синих полос, которые показывают направление x, y и z соответственно. Это работает через axis(length, width) , например:

 put(axis(5,0.1)).on(start); 

Создает этот конечный результат:

Объект оси

Облако точек

Облако точек может быть сгенерировано с множеством маленьких квадратных точек с помощью функции cloud(verts, color, size) . Переменная verts является массивом вершин. Пример облака точек будет выглядеть так:

 var verts = []; for (var i = 0; i < 5000; ++i) { verts.push( v3(Primrose.Random.number( -0.5 * WIDTH, 0.5 * WIDTH), Primrose.Random.number(-0.5 * HEIGHT, 0.5 * HEIGHT), Primrose.Random.number(-0.5 * DEPTH, 0.5 * DEPTH) ) ); } put(cloud( verts, this.options.backgroundColor, 0.05) ).on(start).at(MIDX, MIDY, MIDZ); 

MIDX , MIDY и MIDZ уже являются переменными в нашем примере кода, которые определяют фокус для нашей сцены. Вы можете использовать любые номера на их месте.

Это создает следующее в нашей сцене:

Облако точек в нашей сцене

хаб

Одна вещь, которую вы могли заметить в моих примерах выше, это то, что мы добавляли что-то, называемое start . На самом деле это hub() — особая точка в нашей сцене, в которой мы можем группировать другие объекты. В частности, наш start центр был определен так:

 start = put(hub()) .on(scene) .at(-MIDX, 0, -DEPTH - 2); 

Светлый

Свет можно определить с помощью light(color, [intensity, [distance, [decay]]]) . По умолчанию в нашей сцене используется белый свет, который выглядит так:

 put(light(0xffffff, 1, 500)) .on(start) .at(MIDX + 5, 8, MIDZ + 20); 

коробка

Коробки — и формы после этого — требуют текстурирования, прежде чем они появятся в нашей сцене. Они обернуты в textured() функцию textured() которая дает им текстуру из наших файлов изображений. Формат для коробки выглядит так: box(width, height, length) .

 put(textured(box(2, 2, 2), BRICK)) .on(start).at(MIDX, MIDY, MIDZ); 

Это создает мега-размерный объект Three.js BoxGeometry в нашей сцене:

Простая коробка в нашей сцене

цилиндр

Цилиндры возможны через:

 cylinder( radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded, thetaStart, thetaEnd ) 

Это создает объект Three.js CylinderGeometry . Например, вот цилиндр с верхним и нижним радиусом 1 . Его высота равна 5 а радиус / высота составляет 40 :

 put(textured(cylinder(1, 1, 4, 40, 40), BRICK)) .on(start).at(MIDX, MIDY, MIDZ); 

Это выглядит так:

Цилиндр в нашей сцене

другие

Существует множество других опций, которые вы можете найти в документации Первоцвета в разделе «Функции сценариев» , включая quad() , shell() , sphere() и другие. Исследуйте и экспериментируйте!

Вывод

Primrose — невероятно мощная платформа WebVR, которая, несомненно, послужит основой для некоторых очень полезных VR-приложений в будущем. Несмотря на то, что на ранних этапах как в рамках среды, так и с самим WebVR это были первые годы, похоже, что она будет расти и развиваться с WebVR в отличной форме, так как обе со временем становятся зрелыми.

Любите потенциал здесь? Имейте в виду, что это проект на ранних стадиях, в который вы тоже можете вмешиваться! Свяжитесь с его создателем, Шоном Макбетом , и присоединяйтесь!

Если вы используете Primrose для собственного VR-приложения, я бы хотел увидеть, что вы собрали! Дайте мне знать в комментариях ниже или свяжитесь со мной в Твиттере по адресу @thatpatrickguy .

Если вы находите область виртуальной реальности и WebVR увлекательной, я поговорил с самим Шоном Макбетом о разработке для VR и Primrose на моем сайте Dev Diner . Это одно из моих любимых интервью, которое я когда-либо давал! Шон вдохновляющий парень.