Processing:Библиотеки/Processing for Android/Руководства/Введение в VR

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску


Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.



Введение в VR[1]

В этом руководстве описываются основы для написания VR-приложений при помощи Google VR и Processing.

Google VR

Платформа Google VR позволяет сделать ваш смартфон быстрой отправной точкой в виртуальную реальность. Режим программирования Android в PDE поддерживает платформы Google Cardboard и Google Daydream, поэтому с его помощью можно писать 3D-скетчи, которые можно будет запустить на телефоне как Cardboard-приложения в стерео-режиме и с возможностью отслеживать движения головы. Если вы ранее не делали 3D-скетчи в Processing, то советуем сначала пройти это руководство.

Требования

Чтобы использовать VR-приложения при помощи Cardboard, вам понадобится Cardboard-совместимый телефон с Android 4.1 или выше, гироскоп для отслеживания движений головы и Cardboard-устройство для просмотра виртуальной реальности. Если у вас такого устройства нет, вы все еще сможете просматривать скетч в моно-режиме (подробнее о нем будет рассказано ниже). Для Daydream понадобятся шлем View и Daydream-совместимый телефон.

Если вы используете режим программирования Android версии 4.0-beta3 или новее, все дополнительные пакеты, необходимые для разработки VR-приложений, в этой версии уже есть, поэтому никакой дополнительной возни в этом случае не потребуется. Если вы используете более старую версию режима программирования Android, тогда вам нужно будет отдельно установить библиотеку «processing-cardboard». Она оснащена специальными стерео- и моно-визуализаторами, работающими совместно с датчиками телефона для автоматического обновления камеры Processing. В меню Contribution Manager этой библиотеки нет, поэтому ее нужно будет установить вручную. Для этого сначала установите последнюю версию библиотеки в виде ZIP-архива отсюда, распакуйте ее и скопируйте в папку «/libraries/cardboard» в вашей папке скетчей (т.е. в скетчбуке). Затем перезапустите Processing.

С чего начать

Чтобы скетч создавался как VR-приложение, в PDE нужно выбрать опцию Android > VR:

В базовый скетч для VR необходимо импортировать библиотеку VR и визуализатор STEREO:

import processing.vr.*;

void setup() {
  fullScreen(STEREO);
}

void draw() {
}

Этот код создаст на вашем телефоне пустую стерео-картинку:

Стерео-визуализатор рендерит каждый кадр дважды – по одному для каждого глаза. Для проверки того, какой именно глаз рендерится в текущем вызове draw(), воспользуйтесь в VR-визуализаторе переменной eyeType:

import processing.vr.*;

void setup() {
  fullScreen(STEREO);
}

void draw() {
  PGraphicsVR pvr = (PGraphicsVR)g;
  if (pvr.eyeType == PVR.LEFT) {
    background(200, 50, 50);
  } else if (pvr.eyeType == PVR.RIGHT) {
    background(50, 50, 200);
  } else if (pvr.eyeType == PVR.MONOCULAR) {
    background(50, 200, 50);
  }
}

Вы, возможно, заметили, что значением eyeType также может быть MONOSCOPIC – на тот случай, если вы вместо визуализатора STEREO используете MONO. Моно-визуализатор рисует кадр только один раз, но камера по-прежнему реагирует на движения телефона.

В добавлении в сцену 3D-объектов нет ничего необычного – просто используйте те же функции для рисования 3D-примитивов и фигур, что и при использовании визуализатора P3D. Вы также можете добавить текстуры, источники света и шейдерные эффекты – например, как в скетче ниже (полный код доступен по этой ссылке):

import processing.vr.*;

PShader toon;
boolean shaderEnabled = true;  

void setup() {
  fullScreen(STEREO);  
  noStroke();
  fill(204);
  toon = loadShader("ToonFrag.glsl", "ToonVert.glsl");
}

void draw() {
  if (shaderEnabled == true) shader(toon);
  translate(width/2, height/2);
  background(80); 
  directionalLight(204, 204, 204, 1, 1, -1);
  sphere(150);
}  

void mousePressed() {
  if (shaderEnabled) {
    shaderEnabled = false;
    resetShader();
  } else {
    shaderEnabled = true;
  }
}

Обратите внимание на функцию translate(width/2, height/2) – она необходима для того, чтобы правильно отцентрировать сцену перед глазами пользователя. Это необходимо, потому что Processing по умолчанию помещает начало координат в левый верхний угол экрана, что удобно для 2D-рисования, но для VR – нет. Результат будет выглядеть примерно так:

Создание более сложной сцены

В этом примере мы создадим 3D-сцену, в которой будет чуть больше объектов. Давайте начнем с создания 2D-решетки, которая послужит нам ориентиром для расстановки объектов.

Поскольку производительность очень важна в VR, чтобы частота кадров оставалась как можно выше, а пользователь не испытывал «морской болезни», мы можем положиться на объекты PShape для хранения статичной геометрии и таким образом избежать повторного рендеринга этих объектов в новых кадрах.

import processing.vr.*;

PShape grid;

void setup() {
  fullScreen(STEREO);
  
  grid = createShape();
  grid.beginShape(LINES);
  grid.stroke(255);
  for (int x = -10000; x < +10000; x += 250) {
    grid.vertex(x, +1000, +10000);
    grid.vertex(x, +1000, -10000);
  }
  for (int z = -10000; z < +10000; z += 250) {
    grid.vertex(+10000, +1000, z);
    grid.vertex(-10000, +1000, z);      
  }  
  grid.endShape();  
}

void draw() {
  background(0);
  translate(width/2, height/2);
  shape(grid);
}

Обратите внимание, что значения Y у вершин объекта «grid» равны «+1000». Дело в том, что в Processing значения оси Y перевернуты вверх ногами (если сравнивать с традиционной системой координат), поэтому объекты, расположенные в виртуальной реальности ниже нашей зрительной оси, должны иметь положительные значения оси Y.

Теперь можно добавить немного объектов! Чтобы оптимизировать производительность, мы можем сгруппировать несколько 3D-фигур внутри одной группы объектов PShape, что быстрее, чем если бы мы обрабатывали каждый объект по отдельности. Получится примерно так:

import processing.vr.*;

PShape grid;
PShape cubes;

void setup() {
  fullScreen(STEREO);
  
  grid = createShape();
  grid.beginShape(LINES);
  grid.stroke(255);
  for (int x = -10000; x < +10000; x += 250) {
    grid.vertex(x, +1000, +10000);
    grid.vertex(x, +1000, -10000);
  }
  for (int z = -10000; z < +10000; z += 250) {
    grid.vertex(+10000, +1000, z);
    grid.vertex(-10000, +1000, z);      
  }  
  grid.endShape();  
  
  cubes = createShape(GROUP);
  for (int i = 0; i < 100; i++) {
    float x = random(-1000, +1000); 
    float y = random(-1000, +1000);
    float z = random(-1000, +1000);    
    float r = random(50, 150);
    PShape cube = createShape(BOX, r, r, r);
    cube.setStroke(false);
    cube.setFill(color(180));
    cube.translate(x, y, z);
    cubes.addChild(cube);
  }
}

void draw() {
  background(0);
  lights();
  translate(width/2, height/2);
  shape(cubes);
  shape(grid);
}

Итоговый результат должен выглядеть примерно так (зависит от точки обзора):

См.также

Внешние ссылки