three 蒙皮动画核心过程

简介:

  蒙皮动画:通过模拟人的运动来模拟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>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值