之前有用Threejs的TubeGeometry绘制管道效果,但是TubeGeometry的管道效果默认是圆形的截面,这节实现方形截面的管道绘制。
因为Threejs不提供方形截面的管道,所以使用的是绘制截面,然后拉伸的方式,所以需要先绘制一个方形,当然在此之前还是要先创建一个场景,包括灯光,相机,渲染器等,之前章节已有过就不再贴代码了,下面先通过Shape创建一个截面
const shape = new THREE.Shape();// 创建形状
shape.moveTo(0, 0);
shape.lineTo(2, 0);
shape.lineTo(2, 2);
shape.lineTo(0, 2);
shape.lineTo(0, 0);
然后用CatmullRomCurve3绘制出曲线,也是后面轨道的轨迹,
const curve = new THREE.CatmullRomCurve3([
new THREE.Vector3( -10, -50, -50 ),
new THREE.Vector3( 10, 0, 0 ),
new THREE.Vector3( 8, 50, 50 ),
new THREE.Vector3( -5, 0, 100)
]);
通过ExtrudeGeometry拉伸的方法,将shape截面和曲线curve传入后,进行拉伸,并设置路径的精度,就可以得到一个几何体geometry,再添加一个材质,创建网格模型,添加到场景中。就可以得到下面的3D模型,
const geometry = new THREE.ExtrudeGeometry(shape, { // 创建挤出几何体
extrudePath:curve,//扫描轨迹
steps:100 //沿着路径细分精度,越大越光滑
});
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });// 创建材质
const mesh = new THREE.Mesh(geometry, material); // 创建网格
this.scene.add(mesh);// 将网格添加到场景中
但是这个管道为纯色,下面给这个管道添加贴图,让他更真实,我就随便找了张图片作为贴图,代替原有的材质,完整代码如下:
initExtrudeGeometry(){ // 创建挤出几何体
const shape = new THREE.Shape();// 创建形状
shape.moveTo(0, 0);
shape.lineTo(4, 0);
shape.lineTo(4, 4);
shape.lineTo(0, 4);
shape.lineTo(0, 0);
// 扫描轨迹:创建轮廓的扫描轨迹(3D样条曲线)
const curve = new THREE.CatmullRomCurve3([
new THREE.Vector3( -10, -50, -50 ),
new THREE.Vector3( 10, 0, 0 ),
new THREE.Vector3( 8, 50, 50 ),
new THREE.Vector3( -5, 0, 100)
]);
const geometry = new THREE.ExtrudeGeometry(shape, { // 创建挤出几何体
extrudePath:curve,//扫描轨迹
steps:100 //沿着路径细分精度,越大越光滑
});
const texLoader = new THREE.TextureLoader();//纹理贴图加载器TextureLoader
const texture = texLoader.load('/static/images/cold1.png');// .load()方法加载图像,返回一个纹理对象Texture
const material = new THREE.MeshBasicMaterial({ // 设置纹理贴图:Texture对象作为材质map属性的属性值
map: texture,//map表示材质的颜色贴图属性
});
// 设置阵列模式
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
// uv两个方向纹理重复数量
texture.repeat.set(0.5,0.5);//注意选择合适的阵列数量
// const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });// 创建材质
const mesh = new THREE.Mesh(geometry, material); // 创建网格
this.scene.add(mesh);// 将网格添加到场景中
},
最终的效果如下,不过贴图还是根据实际场景选择,效果会更好