首先说明一下,three.js提供的很多物体都是一个盒子,说白了就是空心的,比如下面我生成了半个圆柱:
var geometry = new THREE.CylinderGeometry( 8,8,20,50,1,true,0,Math.PI);
是长这样的:
是的,这是一片……,而我想要的,是这样的:
所以需要先绘制一个面然后拉升成体。
在three.js中面拉伸成体是用的 THREE.ExtrudeGeometry:
var trackShape = new THREE.Shape();
trackShape.moveTo(10,0);
trackShape.absarc( 0, 0, 10, 0 ,45/180*Math.PI, false );
trackShape.lineTo(50*Math.cos(45/180*Math.PI),50*Math.sin(45/180*Math.PI));
trackShape.absarc( 0, 0, 50, 45/180*Math.PI,0, true );
trackShape.lineTo(9.8,0);
var extrudeSettings = { amount: 10, bevelEnabled: false, steps: 1, };
var geometry = new THREE.ExtrudeGeometry( trackShape, extrudeSettings );
var material = new THREE.MeshPhongMaterial( {color: 0x00EE00,opacity:1,transparent:true} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
其中 trackShape是一个二维的形状,extrudeSettings是如何拉伸,参数比较多,这里主要介绍两个:amount 拉伸的高度,bevelEnabled:是否允许拉伸的时候有斜面,一般情况下设置成false,如果需要请参见相关api文档。
下面再谈谈trackShape,trackShape就是一个平面图像,提供了二维绘图的api,比如绘制直线,圆等,但在使用的时候一定要注意一下两点:
一、绘制一个封闭的图形,最后回到起点的时候,最后一条线会显示不出来,这时候可以稍微调整一点位置,比如x或者y加个0.1之类的
例如上面代码,一开始trackShape.moveTo(10,0);但是结束的时候却是trackShape.lineTo(9.8,0);我们用THREE.Line来观察:
var trackShape = new THREE.Shape();
trackShape.moveTo(10,0);
trackShape.absarc( 0, 0, 10, 0 ,45/180*Math.PI, false );
trackShape.lineTo(50*Math.cos(45/180*Math.PI),50*Math.sin(45/180*Math.PI));
trackShape.absarc( 0, 0, 50, 45/180*Math.PI,0, true );
trackShape.lineTo(10,0);
var geometry = new THREE.ShapeGeometry( trackShape );
var material = new THREE.LineBasicMaterial({color: 0x00EE00});
var line = new THREE.Line( geometry, material );
scene.add( line );
绘制的效果如下:
你会发现这个扇形没有闭合,少了最后一条线段,也就是最后一句 trackShape.lineTo(10,0); 仿佛没有执行一样。这时候我们改成trackShape.lineTo(9.8,0);效果如下:
封闭了。
二、用trackShape绘制封闭的图型的时候,每一段一定要首尾相连的绘制完,不要使用moveTo跳跃起点绘制,否则会绘制额外的线,特别是有绘制圆弧的时候。
上面这句话有点绕,下面举例说明:
var trackShape = new THREE.Shape();
trackShape.moveTo(0,0);
//trackShape.absarc( 0, 0, 10, 0 ,45/180*Math.PI, false );
trackShape.lineTo(50*Math.cos(45/180*Math.PI),50*Math.sin(45/180*Math.PI));
trackShape.absarc( 0, 0, 50, 45/180*Math.PI,0, true );
trackShape.lineTo(0.1,0);
var geometry = new THREE.ShapeGeometry( trackShape );
var material = new THREE.LineBasicMaterial({color: 0x00EE00});
var line = new THREE.Line( geometry, material );
scene.add( line );
上面的代码我绘制一个简单的扇形,如下:
步骤是先设置(0,0)为原点,再绘制了它到(50*Math.cos(45/180*Math.PI),50*Math.sin(45/180*Math.PI))的那条斜线,然后会了一个45度圆弧,最后回到起点,绘制了一条(50,0)到(0.1,0)的直线,可以看到这个扇形是ok的。下面我们变换绘制的方式:
trackShape.moveTo(0,0);
//trackShape.absarc( 0, 0, 10, 0 ,45/180*Math.PI, false );
trackShape.lineTo(50*Math.cos(45/180*Math.PI),50*Math.sin(45/180*Math.PI));
trackShape.moveTo(0,0);
trackShape.lineTo(50,0);
trackShape.moveTo(0,0);
trackShape.absarc( 0, 0, 50, 45/180*Math.PI,0, true );
先绘制了两条直线,再绘制圆弧,图像如下:
很奇怪了,不仅有一条直线没被绘制出来,反而还多了一条线。为了让图像封闭,我们暂时把trackShape.moveTo(0,0);改成trackShape.moveTo(0.1,0);,效果如下:
还是会多一条线,而且这条线是额外加的。