如何弯曲计划实体以匹配球面?

how to curve a plan entity to match a sphere surface?

我对 aframe 有点陌生 我有一个问题:使用 aframe-position-spherical-component,我设法将我的元素定位在 360 度 但是我如何 "curve" 我的元素呢? (以匹配球形显示)(顺便说一句,我的元素是

<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>

<a-curvedimage> 基于圆柱体 (source),因此可能不太适合。
那么实际使用球体几何体怎么样? tldr fiddle here

几何

您可以使用球体的 theta 和 psi 属性使其看起来像 <a-curvedimage>

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

这应该会产生一个 <a-curvedimage> 左右的平面,但也会在垂直轴上弯曲。尝试使用 psi 和 theta 来查看更多三角形或菱形几何形状。

适合球体

这似乎是 custom component 的工作!如果您以前没有使用过它们,请查看 link,否则下面的组件只是简单地复制球体半径和位置并将它们的值用于图像。

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)

或者您可以将内球稍微移向中心 - 就像提供的 fiddle:

// 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 属性,但在这里我们可以操纵 phitheta 值来使图像变大。此外,您应该在放大时将图像放在前面,以防止图像之间出现 z-fighting:

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)
})

fiddlehere。最好将这些值保存在变量中(基值和增量),但我希望这样更容易理解。