three.js-bone

Three.js学习笔记 本篇介绍bone的创建和绑定。完成简单的骨骼动画。

初始化数据、创建骨骼

这里我们使用Cylinder来创建一段几何图形模拟具有骨骼的物体。
你可以比作人的身体而我们创建的bones骨骼以及skeleton骨架就相当于人的脊椎。

    
    //每段高度,这里指骨骼长度
    var segmentHeight = 6;
    
    //分段数量,这里指骨骼数量
	var segmentCount = 1;
	
	//骨架总高度 `6`
	var height = segmentHeight * segmentCount;
	
	//骨架一半的高度 `3`
	var halfHeight = height * 0.5;
	var sizing = {
					segmentHeight: segmentHeight,
					segmentCount: segmentCount,
					height: height,
					halfHeight: halfHeight
				};

    
    function createGeometry(sizing) {
				var geometry = new THREE.CylinderGeometry(
					0.5, //圆柱头部半径
					0.5, //圆柱底部半径
					sizing.height,   // 骨架高度`6` 
					32,
					sizing.segmentCount * 6, // 骨骼数`6`
					true 
				);
				
				//遍历几何图形上的所有顶点
				for (var i = 0; i < geometry.vertices.length; i++) {
				
					var vertex = geometry.vertices[i];
					
					
				/*  计算顶点索引值 `skinIndex` (受那个骨骼影响)
				 *  先将原来 `vertice `顶点的 `y `坐标加上骨架的一半高度,
				 *  相当于将原来在骨架顶部的 `y `轴坐标原点上移到骨骼 `y `轴的中心处
				 *   |                                          |
				 *   |                                          |
				 *   |                +  sizing.halfHeight =    |. `y`坐标原点   
				 *   |                                          |
				 *   |                                          |
				 *   |. `y`坐标原点                                                                               |
				 *
				 *  然后除以骨骼数,然后向下取整便可取到索引值
				 *
				 * */					
					
					
					var y = (vertex.y + sizing.halfHeight);
					var skinIndex = Math.floor(y / sizing.segmentHeight);
					
					
				/*  计算权重`skinWeight`受骨骼影响的比重
				 *   
				 *  y % sizing.segmentHeight (这里的y是偏移过的也就是加了`sizing.halfHeight`)
				 * 
				 *  这里取余可以求出相对一根骨骼底部的偏移量(因为索引值上面已经求出来了)
				 *  再除以骨架的高度,便可以求出相对于权重
				 * 
				 * */					
				 
					var skinWeight = (y % sizing.segmentHeight) / sizing.segmentHeight;
					
					//放入相应的`geometry`属性中
					geometry.skinIndices.push(new THREE.Vector4(skinIndex, skinIndex + 1, 0, 0));
					geometry.skinWeights.push(new THREE.Vector4(1 - skinWeight, skinWeight, 0, 0));
				}
				return geometry;
			};
	

创建骨架和蒙皮


    function createMesh(geometry, bones) {
                
                //创建骨骼材质
				var material = new THREE.MeshPhongMaterial({
					skinning: true,
					color:0xff0000
				});
				
				//创建蒙皮对象
				var mesh = new THREE.SkinnedMesh(geometry, material);
				
				//通过已有的骨骼创建骨架
				var skeleton = new THREE.Skeleton(bones);
				
				//从蒙皮,将蒙皮对象和骨架绑定
				mesh.add(bones[0]);
				mesh.bind(skeleton);
				
				return mesh;
			};

SkinnedMesh

蒙皮对象。

Constructor


    var mesh = THREE.SkinnedMesh( geometry, material );

Main Properties

  • geometry :一种几个图形,需要设置Geometry.skinIndices(索引值)和 Geometry.skinWeights(权重)
  • material :材质,需要设置skinning: true

Skeleton

创建身体


    var geometry = createGeometry(sizing);
	var bones = createBones(sizing);
				
	mesh = createMesh(geometry, bones);
	
	scene.add(mesh);

活动身体

现在只需要在render()里面操作骨骼就可以产生简单的骨骼动画了。

    function render() {
    
			requestAnimationFrame(render);
			renderer.render(scene, camera);
			
			//操作第二个骨骼进行旋转
			mesh.skeleton.bones[1].rotation.x = Math.PI / 180 * 30;
			mesh.skeleton.bones[1].rotation.z = Math.PI / 180 * 30;
			}


outPut

posted @ 2018-09-13 14:55  可爱的黑精灵  阅读(1016)  评论(0编辑  收藏  举报