3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【React Three Fiber】Blenderを使用したメッシュのMorphing

Last updated at Posted at 2021-11-08

概要

Morphとは、メッシュの形状を流動的に変更することを指します。

output(video-cutter-js.com) (1).gif

React Three Fiberのみでこれを実現させようとすると、頂点の座標設定など煩雑なコーディングが必要です。

一方、BlenderでShape Keyを設定したモデルをインポートすることで、簡単にMorphを表現することができます。

サンプル

実際に動くものを触ってみたい方はこちら。

※ この記事とは扱ってるモデルが少し異なります。

Shape Keyの設定

Blenderを使用してShape Keyを設定します。

スクリーンショット 2021-11-08 085053.png

Shape Keyの追加

[+]を押すことで、キーを追加します。

スクリーンショット 2021-11-08 085614.png

  • 最初のBasisは、基準となる形状です。形状を変更していくのはKey 1です。

形状の変更

Key 1を選択した状態で、メッシュの形状を[編集モード]で変更します。

ここで注意点として、
メッシュの頂点数を変更すると、Morphできなくなります。
Cubeの頂点数は8なので、この頂点数8を変えないように形状変更します。

スクリーンショット 2021-11-08 090052.png

  • 上図では、Cubeの上面の頂点を重ねているだけなので、頂点数は8のままです。

Shape Keyの確認

編集モードで形状の変更ができたら、オブジェクトモードに戻ります。
オブジェクトモードに戻ると、メッシュの形状はBasisの状態(変更前の状態)になります。

Key 1の値(Value)を変更することで、メッシュをMorphさせることができます。
値の範囲は、0~1です。

値:0

値:0.5

値:1

ブレンド

Shape Keyで変更される形状は、複数を組み合わせることができます。
例えば、Keyをもうひとつ追加します。

Key 1とKey 2の値をそれぞれ1にすると、形状がブレンドされることがわかります。

glbエクスポート

作成したモデルをglbファイルとしてエクスポートします。
この例では、morph.glbという名前で保存しました。
スクリーンショット 2021-11-08 093018.png
スクリーンショット 2021-11-08 093208.png

React Three Fiberへのインポート

Morph.tsx

Canvasコンポーネントを生成するためのファイル(Morph.tsx)を作成します。

Morph.tsx
import React, { Suspense, VFC } from 'react';
import { OrbitControls, Stats } from '@react-three/drei';
import { Canvas } from '@react-three/fiber';
import { MorphModel } from './MorphModel';

export const Morph: VFC = () => {
	return (
		<Canvas
			camera={{
				position: [0, 5, 10],
				fov: 50,
				aspect: window.innerWidth / window.innerHeight,
				near: 0.1,
				far: 2000
			}}
			dpr={window.devicePixelRatio}
			shadows>

			{/* background */}
			<color attach="background" args={['#1e1e1e']} />
			{/* fps */}
			<Stats />
			{/* control */}
			<OrbitControls />
			{/* light */}
			<directionalLight position={[0, 5, 5]} />
			<ambientLight intensity={0.1} />

			{/* mesh */}
			<Suspense fallback={null}>
				<MorphModel />
			</Suspense>
		</Canvas>
	)
}
  • backgroundでは、Canvasの背景色を設定しています。
  • fpsでは、画面左上にFPSチェッカーを追加しています。
  • controlでは、カメラのコントローラーを追加しています。マウス操作によりカメラを移動することができます。
  • lightでは、シーンのライティングをしています。
  • meshでは、glbファイルを読み込みを行っています。glbファイルを読み込む場合は必ずSuspenseで囲う必要があります。MorphModelは別ファイルに定義しています。

MorphModel.tsx

glbファイルのインポートファイル(MorphModel.tsx)を作成します。

雛形コードの生成

まず、雛形となるコードを生成します。
以下のサイトに、glbエクスポートをしたmorph.glbをドロップすると、glbファイルをインポートするためのコードの雛形が自動で生成されます。

画面右上のコントローラーから、必要な項目を設定します。
特に、TypeScriptでコーディングしている場合は、typesにチェックを入れましょう。

Inkedスクリーンショット 2021-11-08 100709_LI.jpg

ここで、morphTargetプロパティがあれば、設定したShape Keyがちゃんとエクスポートされています。
最後に、**[copy to clipboard]**でコピーします。

雛形ファイルは、コマンドから生成することもできます。
glbファイルの容量の大きく上記のサイトで表示が遅い場合は、こちらが使えます。

glbファイルの追加

プロジェクトにエクスポートしたmorph.glbを追加します。
この例では、以下に配置しました。

public/assets/morph.glb

インポートファイルの作成

コピーしたひな形を元に読み込みファイルを作成します。

MorphModel.tsx
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
*/

import { useControls } from 'leva';
import React, { useRef, VFC } from 'react';
import * as THREE from 'three';
import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader';
import { useGLTF } from '@react-three/drei';

type GLTFResult = GLTF & {
	nodes: {
		Cube: THREE.Mesh
	}
	materials: {
		Material: THREE.MeshStandardMaterial
	}
}

const ModelPath = '/assets/morph.glb'

export const MorphModel: VFC = (props: JSX.IntrinsicElements['group']) => {
	const group = useRef<THREE.Group>()
	const { nodes, materials } = useGLTF(ModelPath) as GLTFResult

	// コントローラーの追加
	const datas = useControls({
		key1: {
			value: 0,
			min: 0,
			max: 1,
			step: 0.01
		},
		key2: {
			value: 0,
			min: 0,
			max: 1,
			step: 0.01
		}
	})

	console.log(nodes.Cube.morphTargetDictionary)
	console.log(nodes.Cube.morphTargetInfluences)

	return (
		<group ref={group} {...props} dispose={null}>
			<mesh
				name="Cube"
				castShadow
				receiveShadow
				geometry={nodes.Cube.geometry}
				material={materials.Material}
				morphTargetDictionary={nodes.Cube.morphTargetDictionary}
				// morphTargetInfluences={nodes.Cube.morphTargetInfluences}
				morphTargetInfluences={[datas.key1, datas.key2]}
			/>
		</group>
	)
}

useGLTF.preload(ModelPath)
  • ModelPathは、morph.glbへのパスを定義しています。
.tsx
const ModelPath = '/assets/morph.glb'
  • console.logで、morphTargetDictionarymorphTargetInfluencesに何が入っているか確認します。
.tsx
console.log(nodes.Cube.morphTargetDictionary)
console.log(nodes.Cube.morphTargetInfluences)

スクリーンショット 2021-11-08 102642.png

morphTargetDictionaryには、Blenderで設定したShape Keyの名前定義の順番がオブジェクトで格納されています。
morphTargetInfluencesには、Shape Keyそれぞれに対する、morphの値が配列で格納されています。この格納順が定義の順番にあたります。初期値は0になっているので、読み込んだメッシュは変形していません。配列の値を0~1まで変化させることで、Morphingさせることができます。

  • コントローラーを追加して、値を変更できるようにします。
.tsx
const datas = useControls({
	key1: {
		value: 0,
		min: 0,
		max: 1,
		step: 0.01
	},
	key2: {
		value: 0,
		min: 0,
		max: 1,
		step: 0.01
	}
})
.tsx
// morphTargetInfluences={nodes.Cube.morphTargetInfluences}
morphTargetInfluences={[datas.key1, datas.key2]}

コントローラーには、levaパッケージを使用しています。levaについて詳しく知りたい方は、以下を参照してください。

Tips

glbエクスポートの仕様

React Three Fiberの記事

過去に投稿した記事です。ご参考までに。

投稿日 タイトル・リンク
2021.10.23 【React】react-three-fibarで3D表現をする(オブジェクトのClippingと断面)
2021.09.22 【React】react-three-fibarで3D表現をする(Mixamoを使ったアニメーションモデル)
2021.09.18 【React】react-three-fibarで3D表現をする(Blenderで作成したモデルの読み込み)
2021.09.18 【React】react-three-fibarで3D表現をする(文字表示)
2021.09.17 【React】react-three-fibarで3D表現をする
2021.06.11 【React × Three.js】Blenderで作成したモデルをReactプロジェクトに読み込む
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?