教育機関向け活用例

6. 面の変形

このセクションでは、面の変形を学びます。
面を変形させることで、波打つような表現などが可能になります。

面の変形

面の変形は、頂点の座標を変更することで行います。
3Dでの形は、たくさんの面が集まってできていますが、 それぞれの面は頂点で構成されています。
そのため、頂点の座標を変更することで、面の形状を変えることができます。

頂点の座標を扱うには、オブジェクトのgeometry属性のattributes.positionを使います。

const position = オブジェクト.geometry.attributes.position

こうして得られたpositionは、各頂点の座標を保持しています。
i 番目の頂点のx座標を取得するには、

const x = position.getX(i)

とします。
また、i 番目の頂点のx座標を変更するには、

position.setX(i, 値)

とします。
頂点の座標を変更したら、position.needsUpdate = true を記述することで変更を反映させます。
環境マップなどの反射を使う場合は、さらに オブジェクト.geometry.computeVertexNormals() で法線を再計算する必要があります。

position.needsUpdate = true
オブジェクト.geometry.computeVertexNormals()

また、position.count で頂点の数を取得できます。

これを使うと、例えばx座標の値に応じてz座標を変えることができます。
segments を指定することを忘れないようにしましょう。planeはデフォルトではsegments: 1になっているので、波打つことができません。
また、フラットシェーディングを有効にすることで、 面の位置の変化をよりわかりやすくしています。

index.html
const { camera, create, animate, controls } = init()

controls.connect()
camera.position.set(-6, 6, 6)

create.ambientLight()
create.directionalLight()

const plane = create.plane({
  size: 10,
  segments: 30,
  option: {
    flatShading: true,
  },
})
const position = plane.geometry.attributes.position

animate(({ time }) => {
  for (let i = 0; i < position.count; i++) {
    const x = position.getX(i)
    position.setZ(i, Math.sin(x + time))
  }
  position.needsUpdate = true
})
index.html
const { camera, create, animate, controls } = init()

controls.connect()
camera.position.set(--6, 6, 6)

create.ambientLight()
create.directionalLight()

const plane = create.plane({
  size: 10,
  segments: 30,
  option: {
    flatShading: true,
  }
})
const position = plane.geometry.attributes.position

animate(({ time }) => {
  for (let i = 0; i < position.count; i++) {
    const x = position.getX(i)
    const y = position.getY(i)
    position.setZ(i, Math.sin(x + time) * Math.cos(y + time))
  }
  position.needsUpdate = true
})

背景を入れると、よりリアルな感じになります。