簡介:
蒙皮動畫:通過模擬人的運動來模擬3D物體的動畫,遊戲中也經常使用。
製作蒙皮動畫的主要過程和注意點:
1. 製作蒙皮骨骼:
var material = new THREE.MeshBasicMaterial({color: 0xfff000,wireframe:true,skinning : true});
mesh = new THREE.SkinnedMesh(geometry,material);
mesh.position.y = 15;
注意這裏的material中的 skinning: true 必須設置爲true,否則蒙皮骨骼不隨骨骼運動。
2. 製作骨頭:
var bones =[];
var arm = new THREE.Bone();
arm.position.y = - 15;
bones.push(arm);
for(var i = 0 ;i<3;i++){
var bone = new THREE.Bone();
bone.position.y = 10;
arm.add(bone);
arm = bone;
bones.push(bone);
}
注意:這裏的思路是先創建一個骨頭arm ,然後循環創建n塊骨頭,分別添加到前一塊骨頭裏。也就是 bone[0] 添加到arm中,bone[1] 添加到bone[0]中,最終實現一個骨頭以此連接的整體骨頭arm,後面用到。
注意2:骨頭arm添加到mesh中的起始位置在mesh的中心點,所以這裏可以設置position.y = - mesh的高度的一半,其他bone的位置以次相對添加它的bone。
3.製作骨架:
var skeleton = new THREE.Skeleton(bones);
4.mesh添加骨頭並且骨架附體:
mesh.add(bones[0]);
mesh.bind(skeleton);
5.最後一步設置geometry每個頂點受哪些骨頭的影響以及影響程度:
for ( var i = 0; i < geometry.vertices.length; i ++ ) {
var vertex = geometry.vertices[ i ];
var y = ( vertex.y + 15 );
var skinIndex = Math.floor( y / 10 );
var skinWeight = ( y % 10 ) / 10;
geometry.skinIndices.push( new THREE.Vector4( skinIndex, skinIndex + 1, 0, 0 ) );
geometry.skinWeights.push( new THREE.Vector4( 1 - skinWeight, skinWeight, 0, 0 ) );
}
注意:這裏var y = ( vertex.y + 15 ); 是因爲我們位移mesh時,geometry的vertices的值沒有變化,所以每個值加了mesh的偏移值,geometry的vertices的值沒有變化的解決方法可以設置geometry.verricesNeedUpdate = true;
注意:這裏的意思每一層的節點受到該層對應的骨頭的影響程度:
案例如下:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>蒙皮</title>
<style>
body{
margin:0;
}
</style>
</head>
<script src="../build/three.js"></script>
<script src="../js/controls/OrbitControls.js"></script>
<script>
function init() {
createScene();
buildAuxSystem();
addBox();
loop();
}
var scene,camera,renderer,width = window.innerWidth,height = window.innerHeight,controls;
var mesh;
function createScene() {
scene = new THREE.Scene;
camera = new THREE.PerspectiveCamera(45,width/height,1,1000);
camera.position.set(0,0,200);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(new THREE.Color(0x333333),1);
renderer.setSize(width,height);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize",handleWindowResize,false)
}
function loop() {
renderer.render(scene,camera);
requestAnimationFrame(loop);
var time = Date.now() * 0.001;
for ( var i = 0; i < mesh.skeleton.bones.length; i ++ ) {
mesh.skeleton.bones[ i ].rotation.z = Math.sin( time ) * 2 / mesh.skeleton.bones.length;
}
}
function handleWindowResize() {
width = window.innerWidth;
height = window.innerHeight;
renderer.setSize(width,height);
camera.aspect = width/height;
camera.updateProjectionMatrix();
}
// 建立輔助設備系統
function buildAuxSystem(){
var gridHelper = new THREE.GridHelper(320,32);
scene.add(gridHelper);
// var axesHelper = new THREE.AxesHelper(320);
// scene.add(axesHelper);
controls = new THREE.OrbitControls(camera,renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.3;
controls.rotateSpeed = 0.35;
controls.enableKeys = false;
controls.update();
}
function addBox() {
var geometry = new THREE.BoxGeometry(10,30,10,1,9,1);
for ( var i = 0; i < geometry.vertices.length; i ++ ) {
var vertex = geometry.vertices[ i ];
var y = ( vertex.y + 15 );
var skinIndex = Math.floor( y / 10 );
var skinWeight = ( y % 10 ) / 10;
geometry.skinIndices.push( new THREE.Vector4( skinIndex, skinIndex + 1, 0, 0 ) );
geometry.skinWeights.push( new THREE.Vector4( 1 - skinWeight, skinWeight, 0, 0 ) );
}
var material = new THREE.MeshBasicMaterial({color: 0xfff000,wireframe:true,skinning : true});
mesh = new THREE.SkinnedMesh(geometry,material);
mesh.position.y = 15;
var bones =[];
var arm = new THREE.Bone();
arm.position.y = - 15;
bones.push(arm);
for(var i = 0 ;i<3;i++){
var bone = new THREE.Bone();
bone.position.y = 10;
arm.add(bone);
arm = bone;
bones.push(bone);
}
mesh.add(bones[0]);
var skeleton = new THREE.Skeleton(bones);
mesh.bind(skeleton);
var skeletonHelper = new THREE.SkeletonHelper(mesh);
scene.add(skeletonHelper);
scene.add(mesh);
}
</script>
<body onload ="init()">
</body>
</html>