Как изогнуть объект плана, чтобы соответствовать поверхности сферы? - PullRequest
0 голосов
/ 23 июня 2019

Я новичок в жизни у меня есть вопрос: с помощью aframe-position-spherical-component мне удалось позиционировать свой элемент в 360deg но как я могу "изогнуть" свой элемент? (чтобы соответствовать сферическому дисплею) (кстати, мой элемент

<html>
  <head>
    <script src="/lib/aframe.min.js"></script>
    <script src="https://unpkg.com/aframe-position-spherical-component/index.js"></script>
  </head>
  <body>
    <a-scene>
      <a-image src="/static/cat.jpeg" width="3" height="1.5" rotation="0 180 0" position-spherical="10 90 180"></a-image>
    </a-scene>
  </body>
</html>

первая попытка решить эту проблему:

на данный момент мне удалось получить что-то близкое к тому, что я хочу, но значение было найдено вручную и не идеально

<a-curvedimage src="/static/cat.jpeg" width="3" height="1.5" theta-length="64" radius="3" theta-start="-32" rotation="0 180 0" position-spherical="10 90 180"></a-curvedimage>

вторая попытка (с решением a-сферы):

вроде работает, но изображение зеркально отражается, и добавить событие клика, например, чтобы увеличить изображение, трудно достичь

<a-assets>
  <img id="cat" src="/static/cat.jpeg" />
</a-assets>
<a-box scale="0.1 0.1 0.1" color="red"></a-box>
<a-sphere radius="10" geometry="phiLength: 20; thetaLength: 14.12; thetaStart: 65" rotation="0 210 0" material="side: back; shader: flat; src: #cat"></a-sphere>
<a-sphere radius="10" geometry="phiLength: 20; thetaLength: 14.12; thetaStart: 65" rotation="0 240 0" material="side: back; shader: flat; src: #cat"></a-sphere>
<a-sphere radius="10" geometry="phiLength: 20; thetaLength: 14.12; thetaStart: 65" rotation="0 270 0" material="side: back; shader: flat; src: #cat"></a-sphere>
<a-sphere radius="10" geometry="phiLength: 20; thetaLength: 14.12; thetaStart: 65" rotation="0 300 0" material="side: back; shader: flat; src: #cat"></a-sphere>

1 Ответ

1 голос
/ 25 июня 2019

<a-curvedimage> основан на цилиндре ( источник ), поэтому он может не подходить.
Так как насчет использования геометрии сферы? Tldr Fiddle здесь

Геометрия

Вы можете сделать его похожим на <a-curvedimage>, используя свойства сферы theta и psi:

<a-sphere geometry='thetaStart: 45; thetaLength: 45; psiLength: 45'></a-sphere>

Это должно привести к плоскости <a-curvedimage>, но также изогнутой по вертикальной оси. Поиграйте с пси и тэтой, чтобы увидеть больше треугольников или ромбовидных геометрий.

Вписывается в сферу

Это похоже на работу для пользовательского компонента ! Если вы не использовали их ранее, проверьте ссылку, в противном случае компонент ниже просто копирует радиус и положение сферы и использует их значения для изображения.

AFRAME.registerComponent('foo', {        
  schema: {
     // we'll use it to provide the sphere
     target: {type: selector}            
  },
  init: function() {
     let sphere = this.data.target
     // make sure the sphere radius and transform is identical:
     this.el.setAttribute('radius', sphere.getAttribute('radius'))
     this.el.setAttribute('position', sphere.getAttribute('position'))
  }
})

И просто используйте это так:

<!-- the background with some position and radius -->
<a-sphere id='background'></a-sphere>
<!-- the inner sphere  -->  
<a-sphere foo='target: #background'></a-sphere>

Z-Fighting

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

С этим легко справиться - изменив радиус внутренней сферы:

 this.el.setAttribute('radius', sphere.getAttribute('radius') * 0.95)

Или вы можете немного переместить внутреннюю сферу к центру - как в предоставленной скрипке:

// grab the inner sphere's mesh
let mesh = this.el.getObject3D('mesh')
// we need an axis - I'd substract the mesh's center from the spheres center
let axis = sphere.getAttribute('position').clone()
axis.add(mesh.geometry.boundingSphere.center.clone().multiplyScalar(-1))
axis.normalize();
// move the inner sphere a bit along the axis
this.el.object3D.translateOnAxis(axis, 0.05)

Увеличение изображения при нажатии

Обычно мы используем атрибут scale, но здесь мы можем манипулировать значениями phi и theta, чтобы увеличить изображение. Также вы должны вывести изображение на передний план при увеличении, чтобы предотвратить z-бой между изображениями:

this.el.addEventListener('click', e => {
   this.clicked = !this.clicked
   // preset values depending if the image is clicked or not
   let thetaLength = this.clicked ? 65 : 45
   let thetaStart = this.clicked ? 35 : 45
   let psiLength = this.clicked ? 65 : 45
   let psiStart = this.clicked ? -10 : 0
   let scale = this.clicked ? 0.95 : 1
   // apply the new geometry 
   this.el.setAttribute('geometry', {
    'thetaLength': thetaLength,
    'thetaStart': thetaStart,
    'phiLength': psiLength,
    'phiStart' : psiStart
   })
   this.el.setAttribute('radius', sphere.getAttribute('radius') * scale)
})

скрипка здесь . Было бы лучше сохранить эти значения в переменных (базовое значение и дельта), но я надеюсь, что таким образом легче понять.

...