<html>
<head>
<title>A-Frame VRM with Patched MMDLoader (Final)</title>
<meta charset="utf-8">
<script type="importmap">{"imports": {"three": "https://threejs.org/build/three.module.js"}}</script>
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://unpkg.com/three@0.125.2/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.125.2/examples/js/loaders/TGALoader.js"></script>
<script src="https://unpkg.com/three@0.125.2/examples/js/animation/MMDAnimationHelper.js"></script>
<script src="https://unpkg.com/three@0.125.2/examples/js/loaders/MMDLoader.js"></script>
<script src="https://binzume.github.io/aframe-vrm/dist/aframe-vrm.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// aframe-vrmが定義されるのを待つため、少し遅延させます
setTimeout(() => {
if (AFRAME.components['vrm-anim'] && AFRAME.components['vrm-anim'].Component.prototype.update) {
console.log("Applying monkey patch to aframe-vrm's 'update' method...");
const vrmAnimProto = AFRAME.components['vrm-anim'].Component.prototype;
// 元のupdate関数を保存
const originalUpdate = vrmAnimProto.update;
// update関数を我々のカスタム関数で上書き
vrmAnimProto.update = function(oldData) {
const data = this.data;
// srcプロパティが指定されており、初回または変更された場合に処理
if (data.src && (!oldData || data.src !== oldData.src)) {
// VMDファイルの場合、我々のパッチが動作
if (data.src.toLowerCase().endsWith('.vmd')) {
console.log("VMD file detected. Using patched loader.");
const loader = new THREE.MMDLoader();
const el = this.el;
loader.load(data.src, (vmd) => {
// 読み込み成功後、vrm-animコンポーネントが内部で持つmixerにアニメーションをセット
const clip = vmd.animations[0];
if (this.mixer) {
this.mixer.stopAllAction();
const action = this.mixer.clipAction(clip);
action.setLoop(data.loop ? THREE.LoopRepeat : THREE.LoopOnce);
action.play();
el.emit('animation-loaded', {clip: clip, action: action});
console.log("Patched VMD animation started.");
} else {
console.error("VRM mixer not ready yet. Animation could not be played.");
}
}, undefined, (err) => {
console.error("Patched MMDLoader failed to load VMD.", err);
});
return; // パッチ処理をしたので、元のupdateは呼ばない
}
}
// VMD以外、またはsrcに変更がない場合は、元のupdate処理を呼び出す
originalUpdate.apply(this, arguments);
};
} else {
console.error("Failed to apply monkey patch. 'vrm-anim' component or its 'update' method not found.");
}
}, 500); // 念のため500ミリ秒待つ
});
</script>
</head>
<body style="background-color: black; color:white;">
<a-scene>
<a-entity
vrm="src:./vrm/tesA1_V0a.vrm"
vrm-anim="src:./vrm/hand.vmd"
position="0 0 -2"
scale="1.2 1.2 1.2"
rotation="0 180 0">
</a-entity>
<a-camera position="0 1.2 4"></a-camera>
<a-sky color="#444"></a-sky>
<a-plane position="0 0 0" rotation="-90 0 0" width="30" height="30" color="#222"></a-plane>
<a-light type="directional" color="#FFF" intensity="1" position="-1 2 2"></a-light>
<a-light type="ambient" color="#AAA"></a-light>
</a-scene>
</body>
</html>
使用変数
) { // aframe-vrmが定義されるのを待つため、少し遅延させます setTimeout -------( Function ) | |
action | |
anim | |
charset | |
clip | |
color | |
data | |
el | |
height | |
intensity | |
loader | |
originalUpdate | |
position | |
rotation | |
scale | |
src | |
style | |
type | |
update | |
vrm | |
vrmAnimProto | |
width |