Three.js では BlendShape = MorphTarget(モーフターゲット) と呼ばれ、
mesh.morphTargetInfluences を操作することで口形状・表情を動かせる
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
let scene, camera, renderer;
let model;
function init() {
// シーン・カメラ・レンダラー
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 1.5, 3);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// ライト
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(1, 1, 1);
scene.add(light);
// GLTF 読み込み
const loader = new GLTFLoader();
loader.load('model.glb', (gltf) => {
model = gltf.scene;
scene.add(model);
// 読み込み後にブレンドシェイプを確認
model.traverse((obj) => {
if (obj.isMesh && obj.morphTargetInfluences) {
console.log("MorphTargets:", obj.morphTargetDictionary);
}
});
});
animate();
}
function animate() {
requestAnimationFrame(animate);
// BlendShape(MorphTarget)を動かす例
if (model) {
model.traverse((obj) => {
if (obj.isMesh && obj.morphTargetInfluences) {
// 例:口「あ」を 0〜1 でアニメーション
const t = (Math.sin(Date.now() * 0.002) + 1) / 2;
// "A" という名前のモーフがある場合を想定
const index = obj.morphTargetDictionary["A"];
if (index !== undefined) {
obj.morphTargetInfluences[index] = t; // 0〜1で動かす
}
}
});
}
renderer.render(scene, camera);
}
init();