В этой небольшой статье я расскажу вам о трудностях, которые встретил на пути создания интерактивной панорамы на WebGL + THREE.js.
Определим требования к панораме:
- используем WebGL, так как Canvas панорамы просто ужас, и еще новый IE поддерживает;
- Просмотр панорамы путем перетаскиванием зажатой кнопки мыши;
- Активные элементы призванные обратить внимание и сообщить информацию;
- Возможность посмотреть несколько панорам на одной странице.
Что бы понять, как это реализовать, предлагаю представить следующее: «Мы находимся в центре сферы, на внутреннюю поверхность которой нанесена текстура панорамы. Мы — это камера, которая может поворачиваться и смотреть вверх или вниз. На внутренней поверхности сферы ( „у“ поверхности, как оказалось ) находятся элементы, и когда мы наводим на них мышку, появляется окошко с информацией».
Cфера
Существует как минимум два варианта реализации панорамы: кубическая и сферическая. Я выбрал сферическую, так как размещение визуально одинаковых активных элементов предполагает равноудаленное расстояние от центра. За прототип возьмем существующий образец панорамы с сайта разработчика библиотеки. Он нам полностью подходит за одним исключением. Это сфера с текстурой вывернутая на изнанку. Трудно представить как это может выглядеть.
mesh.scale.x = -1;
К сожалению, одна эта деталь ставит полный крест на возможности добавления элементов. Суть в том, что получить хоть какую то информацию об объекте в пространстве при помощи указателя, надо «выстрелить» лучом (Raycaster) из точки указателя в направление вектора, только в данном случае луч не ударится о стенку сферы, потому как камера (логичная точка начала) не находится внутри. Сделано это потому, что текстура натягивается только с внешней стороны, но теперь есть возможность это исправить просто добавив свойство side в объект материи сферы:
mesh = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/2294472375_24a3b8ef46_o.jpg' ) side: THREE.BackSide } ) );
Кстати, это типичное создание объекта в мире THREE.js. Как правило создается геометрия объекта, материал ( текстура ), а потом добавляется на сцену.
Элементы
Теперь надо подумать о том, что из себя будут представлять те самые активные элементы. В идеале ими должны быть плоские спрайты, всегда отображающиеся лицом к камере. Да, да именно так 🙂
Но здесь нас ждет сюрприз. В THREE.js существует два «класса» для рендеринга: WebGLRenderer и CanvasRenderer. И два типа простых объектов: Particle (частица) и Sprite. WebGL работает с Sprite, а Canvas с Particle. При этом нам необходим именно WebGL, а объект Sprite не имеет объема в пространстве. То есть по нему невозможно попасть мышкой.
Что ж возьмем и с имитируем эти самые спрайты при помощи 3D объекта с геометрией плоскости ( PlaneGeometry):
var itemGeometry = new THREE.PlaneGeometry(35, 35), pointMapHovered = THREE.ImageUtils.loadTexture( "img/information-hover.PNG" ), pointMap = THREE.ImageUtils.loadTexture( "img/information-unhover.PNG" ); point = new THREE.Mesh( itemGeometry, new THREE.MeshBasicMaterial({ map: pointMap, transparent:true //планка квадратная, не думаю, что кому-нибудь понравятся черные углы }) );
Хочу обратить ваше внимание, почему именно так: закеширована геометрия точки и текстура, а материал будет каждый раз создаваться заново. Дело в том, что при наведении мышки на точку, мы будем подменять текстуру на более яркую, к примеру, но если MeshBasicMaterial закеширована и является для всех общей, загораться будут все. Насчет наведения мышкой, все просто — берем отсюда.
Последняя важная часть, которая вызвала затруднения — это перерасчет координат области панорамы на странице на координаты WebGL пространства для точного выделения точек. Визуально элементы видны, но их координаты на страничке не совпадают с координатами 3D пространства. На StackOverFlow нашелся ответ.
Данные
Так как предполагается возможность просматривать много панорам на одной странице, лучше все данные поместить в JSON. Примерно так:
{ "points": [ { "coords": { "x": 302.0282521739266, "y": -32.30522607035554, "z": 389.86440214968525 }, "header": "Заголовок", "body": "Описание." }, ], "texture": "panorama.jpg", "name": "название панорамы" }
Что бы просматривать разные панорамы, мы будем подменять текстуру сферы, удалять точки и по координатам выстраивать новые.
Что получилось
Приглашаю посмотреть
ссылка на оригинал статьи http://habrahabr.ru/post/184488/
Добавить комментарий