在 AFrame 中随时随地操作顶点?

问题描述

我有一架定制飞机:

JS:

AFRAME.registerGeometry('example',{
      schema: {
        vertices: {
          default: ['-10 10 0','-10 -10 0','10 -10 0','10 -10 0'],}
      },init: function (data) {
        var geometry = new THREE.Geometry();
        geometry.vertices = data.vertices.map(function (vertex) {
            var points = vertex.split(' ').map(function(x){return parseInt(x);});
            return new THREE.Vector3(points[0],points[1],points[2]);
        });
        geometry.computeBoundingBox();
        geometry.faces.push(new THREE.Face3(0,1,2));
        geometry.faces.push(new THREE.Face3(0,2,3));
        geometry.mergeVertices();
        geometry.computeFacenormals();
        geometry.computeVertexnormals();
        this.geometry = geometry;
      }
    });

HTML:

<a-entity id="myPlane" geometry="primitive: example; vertices: 1 1 -3,3 1 -3,2 2 -3,1 2 -3"></a-entity>

现在如何操作动画循环中的顶点位置?

先说第一点:

geometry.vertices[0] 

我知道我可以通过以下方式访问网格:

document.getElementById("myPlane").object3D;

并改变它的位置,例如:

document.getElementById("myPlane").object3D.position.set(1,0)

但是平面网格的几何体上没有顶点:

document.getElementById("plane").object3D.children[0]

如何操作几何体的顶点?

编辑:

我发现你可以像这样更新顶点的位置:

document.getElementById("myPlane").object3D.children[0].geometry.attributes.position.array[0] = 20;

document.getElementById("myPlane").object3D.children[0].geometry.attributes.position.needsUpdate = true;

想在 tick() 函数中进行整个操作,因为我真正想要的是用一条线连接两个对象。

现在平面的顶点看起来像这样:

Float32Array(18) [-0,-3,-3]

因为飞机有 4 个点,我预计会有 4*3 = 12 个元素,但我们这里有 18 个元素。 xyz 旁边还有什么?

解决方法

顶点可用作对象几何的属性:

// mesh
const mesh = element.getObject3D("mesh");
// "vertices"
const vertices = mesh.geometry.attributes.position.array;

您可以简单地更改任何您想要的内容,并使用以下命令确认更新:

mesh.geometry.attributes.position.needsUpdate = true;

索引非索引几何之间的差异带来了巨大的复杂性。简而言之:

  • 非索引 几何体包含网格中任何三角形的所有顶点。一个平面包含两个三角形,因此有 2 个三角形 * 3 个顶点 * 3 个坐标 = 18 个条目。在这个例子中可以说明这一点,我操作了一个顶点,但只有一个三角形受到影响:

<script src="https://aframe.io/releases/1.0.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("foo",{
    init: function() {
      this.el.addEventListener("loaded",e => {
        const mesh = this.el.getObject3D("mesh");
        this.positionAttr = mesh.geometry.attributes.position;
      })
    },tick: function(time) {
      // manipulate "Y" of the third vertex
      let offset = 0.25 * Math.sin(time * 0.001);
      this.positionAttr.array[2 * 3 + 1] = 0.5 + offset;
      this.positionAttr.needsUpdate = true;
    }
  })
</script>

<a-scene>
  <a-plane position="0 1.5 -2" wireframe="true" material="color: blue" foo></a-plane>
</a-scene>

  • indexed 几何不喜欢将相同的顶点重复两次,因此它存储唯一的顶点,并提供引用任何存储顶点的“索引”。现在操纵顶点看起来完全不同:

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("foo",tick: function(time) {
      let offset = 0.25 * Math.sin(time * 0.001);
      this.positionAttr.array[4] = 0.5 + offset;
      this.positionAttr.needsUpdate = true;
    }
  })
</script>

<a-scene>
  <a-plane position="0 1.5 -2" wireframe="true" material="color: blue" foo></a-plane>
</a-scene>

代码看起来相同,但 a-frame 版本不同 - 更改几何图形时应该得到相同的结果 (geometry.toNonIndexed())

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...