X
2020年09月30日 - WebVR・Three.js

球体の頂点アニメーション

球体の頂点アニメーション

Three.jsでいろいろと制作できるようになりたいと思い、「Learning 3D Graphics With Three.js | Dynamic Geometry」を参考に、球体の頂点アニメーションを試してみました。

※Three.jsの仕様が変更になったため内容を修正しました。Three.jsはr126を使用しています。(2021年3月27日)

球体の頂点アニメーション

● 球体を生成

まずは、SphereGeometryを使用して球体を生成します。動作確認のため、マテリアルはライティングを必要としないMeshNormalMaterialを使用します。

球体を生成
const geometry = new THREE.SphereGeometry(3,128,128);
const material = new THREE.MeshNormalMaterial();
const sphere = new THREE.Mesh(geometry,material);
scene.add(sphere);

● 球体の頂点を取得

球体の頂点を取得します。Three.jsのr125からGeometryが廃止され、SphereGeometryはBufferGeometryを継承するようになったため、BufferGeometryと同じ要領で球体の頂点を取得します。

const positions = sphere.geometry.attributes.position.array;

for(let i = 0; i < positions.length; i++){
}

● 球体の頂点を操作

取得した頂点を単位ベクトルにし、ランダムな値を積算して球体を凸凹にします。

ベクトルは方向と長さの情報を持ち、長さが1のベクトルのことを単位ベクトルといいます。取得した頂点をnormalizeで正規化し、単位ベクトルにします。

球体の頂点を操作

perlin.js」はパーリンノイズを生成するライブラリで、noise.perlin3(x,y,z)でノイズを生成します。単位ベクトルに対し、multiplyScalarでランダムな値(パーリンノイズ)を積算して球体を凸凹にします。

const positions = sphere.geometry.attributes.position.array;

for(let i = 0; i < positions.length; i++){
	const p = new THREE.Vector3(
		positions[i*3],
		positions[i*3+1],
		positions[i*3+2]
	);

	p.normalize().multiplyScalar(r + 0.3 * noise.perlin3(p.x * k + time, p.y * k, p.z * k));

	positions[i*3] = p.x
	positions[i*3+1] = p.y
	positions[i*3+2] = p.z;
}

頂点座標の更新を通知して、レンダリングします。

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

法線は面に対して垂直に伸びる線のことで、光の反射などに影響します。法線を設定すると、影ができて立体的になります。

法線を設定します

法線を設定するため、更新を通知します。

sphere.geometry.computeVertexNormals();

● 頂点アニメーション

球体の頂点をアニメーションさせます。performance.nowでタイムスタンプを取得し、パーリンノイズの値に加算してアニメーションさせます。

球体の頂点をアニメーションさせます
let sphere;

const geometry = new THREE.SphereBufferGeometry(3,128,128);
const material = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh(geometry,material);
scene.add(sphere);

function rendering(){
	requestAnimationFrame(rendering);

	//タイムスタンプの取得
	const time = performance.now() * 0.001;
	const positions = sphere.geometry.attributes.position.array;

	//球体の半径
	const r = 3;

	//ノイズのサイズ調整
	const k = 2;

	for(let i = 0; i < positions.length; i++){
		const p = new THREE.Vector3(
			positions[i*3],
			positions[i*3+1],
			positions[i*3+2]
		);

		p.normalize().multiplyScalar(r + 0.3 * noise.perlin3(p.x * k + time, p.y * k, p.z * k));

		positions[i*3] = p.x
		positions[i*3+1] = p.y
		positions[i*3+2] = p.z;
	}

	sphere.geometry.attributes.position.needsUpdate = true;
	sphere.geometry.computeVertexNormals();

	renderer.render(scene,camera);
}

完成したデモになります。マテリアルはMeshNormalMaterialからMeshPhysicalMaterialに変更し、PointLightを使用してライティングを調整しました。

  • このエントリーをはてなブックマークに追加

関連記事

スポンサーリンク

前の記事へ

Three.jsで星空を制作

次の記事へ

Three.jsでラインアニメーション