前言
本文可以实现对MMD模型的引入以及动作、镜头文件的绑定模型的功能,实现在web端播放MMD文件的效果。
须知
比较幽默的是threejs官方在r172版本把mmdloader给去除了
官方的说法
官方给出的补充方案(这个更幽默)
MMD相关知识
模型文件是pmx,模型会有贴图,不要只把mmd资源中的pmx单独提出来会导致模型加载的问题
动作文件和镜头文件是vmd,通常单独为一个文件。
我建议初学的人直接去模之屋找别人已经做好的,地址:www.aplaybox.com
技术版本
| 技术 | 版本 |
|---|---|
| node.js | 18.20.7 |
| three.js | 0.170.0 |
three引入:
npm install three@0.170.0
主要代码内容
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="./styles/main.css" rel="stylesheet" type="text/css">
<style>
body {
margin: 0;
}
</style>
<script src="./node_modules/three/examples/jsm/libs/ammo.wasm.js"></script>
<script type="module" src="./main.js"></script>
</head>
<body>
<div id="scene-container">
</div>
</body>
</html>
main.css
body {
/* remove margins and scroll bars */
margin: 0;
overflow: hidden;
/* style text */
text-align: center;
font-size: 12px;
font-family: Sans-Serif;
/* color text */
color: #444;
width: 100vw;
height: 100vh;
}
h1 {
/* position the heading */
position: absolute;
width: 100%;
/* make sure that the heading is drawn on top */
z-index: 1;
}
#scene-container {
/* tell our scene container to take up the full page */
position: absolute;
width: 100%;
height: 100%;
/*
Set the container's background color to the same as the scene's
background to prevent flashing on load
*/
background-color: black;
}
main.js
// 引入three.js
import * as THREE from 'three';
// 引入控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 引入MMDLoader
import { MMDLoader } from 'three/examples/jsm/loaders/MMDLoader.js';
import { MMDAnimationHelper } from 'three/examples/jsm/animation/MMDAnimationHelper.js';
// 引入容器元素
const container = document.querySelector('#scene-container');
// 创建场景
const scene = new THREE.Scene();
// 设置场景背景色
scene.background = new THREE.Color('#999999');
// 相机参数设置
const fov = 35; // 视角
const aspect = container.clientWidth / container.clientHeight; // 宽高比
const near = 0.1; // 最近距离
const far = 900; // 最远距离
// 创建相机
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
// 设置相机位置
camera.position.z = 75;
camera.position.y = 2;
camera.position.x = 2;
// 设置相机朝向
camera.lookAt(0, 0, 0);
// 添加世界坐标辅助器,可选
// const axesHelper = new THREE.AxesHelper(5);
// scene.add(axesHelper);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 渲染器设置
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.physicallyCorrectLights = true;
// 将渲染器dom添加到容器中
container.append(renderer.domElement);
// 创建控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置阻尼
controls.enableDamping = true;
// 设置阻尼系数
controls.dampingFactor = 0.05;
// 添加环境光
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
// 创建平行光
const light = new THREE.DirectionalLight(0xffffff, 1);
// 设置平行光位置
light.position.set(1, 1, 1);
// 添加平行光
scene.add(light);
// 创建MMDLoader
const mmdLoader = new MMDLoader();
// 创建MMDAnimationHelper
const helper = new MMDAnimationHelper();
// 时间轴
const clock = new THREE.Clock();
// 加载mmd
Ammo().then(function (AmmoLib) {
Ammo = AmmoLib;
mmdLoader.loadWithAnimation(
'模型文件.pmx',// 替换为你所需要的模型文件路径
'动作文件.vmd',// 替换为你所需要的动作文件路径
function (mmd) {
// console.log(mmd);
// 回调中添加模型到场景中
scene.add(mmd.mesh);
helper.add(mmd.mesh, {
animation: mmd.animation,
physics: true,
});
mmdLoader.loadAnimation(
'镜头文件.vmd',// 替换为你所需要的镜头文件路径
camera,
function (cameraAnimation) {
helper.add(camera, {
animation: cameraAnimation,
});
},
null,
null
);
// 执行渲染
function animate() {
controls.update();
requestAnimationFrame(animate);
helper.update(clock.getDelta());
renderer.render(scene, camera);
}
animate();
}
);
});
重点关注
ammo.wasm.js文件可以自己从其他地方弄,但是我偷懒直接从依赖中引入了,这个一定要引入
效果图
结语
官方文档现在都没有mmd例子了,如果大家想看mmd的例子建议去找官方的旧文档下下来自己部署看,这只是一个简单的例子,还有一些内容深入得看各位的学习能力了