【问题标题】:how to curve a plan entity to match a sphere surface?如何弯曲平面实体以匹配球面?
【发布时间】:2019-11-05 17:12:54
【问题描述】:

我对 aframe 有点陌生 我有一个问题:使用 aframe-position-spherical-component,我设法将我的元素定位在 360 度 但是我怎样才能“弯曲”我的元素呢? (以匹配球形显示)(顺便说一句,我的元素是

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

【问题讨论】:

    标签: aframe curve spherical-coordinate


    【解决方案1】:

    &lt;a-curvedimage&gt; 基于圆柱体 (source),因此可能不太适合。
    那么实际使用球体几何呢? tldr fiddle here

    几何

    您可以使用球体的 theta 和 psi 属性使其看起来像 &lt;a-curvedimage&gt;

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

    这应该会产生一个&lt;a-curvedimage&gt;ish 平面,但也会在垂直轴上弯曲。玩转 psi 和 theta 以查看更多三角形或菱形几何形状。

    拟合成球体

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

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

    您应该注意到图像不可见或变形。现在我们有两个大小和变换相同的球体,所以渲染器不会知道哪个在另一个之前。

    您可以轻松解决这个问题 - 通过更改内球体的半径:

     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 属性,但在这里我们可以操作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)
    })
    

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

    【讨论】:

    • 你好@PiotrAdamMilewski。你的解决方案有点工作。我移除了球体,因为它不是我项目的一部分(我想在 360 度中显示 10 个图像)。问题是,通过您的解决方案,单击图像以查看更大的图像确实很难实现。另外,我看到镜像了,正常吗?
    • 如果你想让它变大'onClick'那么你可以像我here那样操作theta和phi。图像被镜像可能是因为它位于网格的背面。一个巧妙的技巧是像我一样设置material.repeat = -1 here
    • 太棒了。最后一个小问题,如果我想让点击的图像在另一个之前,我只是喜欢this.el.setAttribute('radius', sphere.getAttribute('radius') * 0.95) ?
    • @xDelph 你可以这样:a) firstclick - set radius *0.95 b) secondclick - setRadius * 1. 它适合你吗?
    • @xDelph 我已将大部分内容添加到 anwser
    猜你喜欢
    • 2014-12-12
    • 2021-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 2023-03-30
    • 1970-01-01
    • 2016-03-22
    相关资源
    最近更新 更多