友情链接:threejs 中文文档
1. 几何体方法.setFromPoints()
三维向量Vector3表示顶点坐标
用三维向量Vector3表示顶点的x、y、z坐标,作为数组元素创建一组顶点坐标
const pointsArr = [
// 三维向量Vector3表示的坐标值
new THREE.Vector3(0,0,0),
new THREE.Vector3(0,100,0),
new THREE.Vector3(0,100,100),
new THREE.Vector3(0,0,100),
];
.setFromPoints() 方法
.setFromPoints()是几何体BufferGeometry的一个方法,通过该方法可以把数组pointsArr中坐标数据提取出来赋值给几何体。具体说就是把pointsArr里面坐标数据提取出来,赋值给geometry.attributes.position属性
// 把数组pointsArr里面的坐标数据提取出来,赋值给`geometry.attributes.position`属性
geometry.setFromPoints(pointsArr);
console.log('几何体变化',geometry.attributes.position);
2. 曲线Curve
threejs提供了很多常用的曲线或直线API,可以直接使用。这些API曲线都有一个共同的父类Curve
曲线Curve方法.getPoints()
椭圆弧线EllipseCurve的父类是曲线Curve,自然会继承父类曲线.getPoints()方法,通过.getPoints()可以从曲线上获取顶点数据。
通过方法.getPoints()可以从曲线上按照一定的细分精度返回沿着曲线分布的顶点坐标。细分数越高返回的顶点数量越多,自然轮廓越接近于曲线形状。方法.getPoints()的返回值是一个由二维向量Vector2或三维向量Vector3构成的数组,Vector2表示位于同一平面内的点,Vector3表示三维空间中一点。
//getPoints是基类Curve的方法,平面曲线会返回一个vector2对象作为元素组成的数组
const pointsArr = arc.getPoints(50); //分段数50,返回51个顶点
console.log('曲线上获取坐标',pointsArr);
曲线Curve方法.getSpacedPoints()
.getSpacedPoints() 也是提取曲线的顶点数据,不同的是getSpacedPoints()方法是按照曲线长度等距来获取顶点数据,而getPoints()会考虑到斜率的变化,斜率变化快的位置顶点会更密集
3. 样条曲线
对于一些不规则的曲线,很难用圆弧去描述,可以使用threejs中的样条曲线和贝尔曲线来实现
三维样条曲线CatmullRomCurve3
在三维空间中随意设置几个顶点坐标,然后作为三维样条曲线CatmullRomCurve3的参数,你就可以生成一条穿过这几个点的光滑曲线。
// 三维向量Vector3创建一组顶点坐标
const arr = [
new THREE.Vector3(-50, 20, 90),
new THREE.Vector3(-10, 40, 40),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(60, -60, 0),
new THREE.Vector3(70, 0, 80)
]
// 三维样条曲线
const curve = new THREE.CatmullRomCurve3(arr);
二维样条曲线SplineCurve
CatmullRomCurve3是3D样条曲线API,曲线经过的点可以在3D空间中任何一个位置,二维样条曲线SplineCurve默认情况下就是在XOY平面生成一个平面的样条曲线。 SplineCurve的参数是二维向量对象Vector2构成的数组。
// 二维向量Vector2创建一组顶点坐标
const arr = [
new THREE.Vector2(-100, 0),
new THREE.Vector2(0, 30),
new THREE.Vector2(100, 0),
];
// 二维样条曲线
const curve = new THREE.SplineCurve(arr);
将样条曲线通过线模型Line显示
使用前面介绍的getPoints() 方法,获取曲线上任意数量的点的坐标,复制给BufferGeometry几何体,通过线模型Line可以将其曲线可视化出来
//曲线上获取点
const pointsArr = curve.getPoints(100);
const geometry = new THREE.BufferGeometry();
//读取坐标数据赋值给几何体顶点
geometry.setFromPoints(pointsArr);
// 线材质
const material = new THREE.LineBasicMaterial({
color: 0x00fffff
});
// 线模型
const line = new THREE.Line(geometry, material);
4. 贝塞尔曲线
二维二次贝塞尔曲线QuadraticBezierCurve
二维二次贝塞尔曲线,参数为三个二维向量对象
// p2为曲线的控制点
const p1 = new THREE.Vector2(-80, 0);
const p2 = new THREE.Vector2(20, 100);
const p3 = new THREE.Vector2(80, 0);
const curve = new THREE.QuadraticBezierCurve(p1, p2, p3);
三维二次贝赛尔曲线QuadraticBezierCurve3
三维二次贝赛尔曲线,参数为三个三维向量对象
// p2为曲线的控制点
const p1 = new THREE.Vector3(-80, 0, 0);
const p2 = new THREE.Vector3(20, 100, 0);
const p3 = new THREE.Vector3(80, 0, 100);
const curve = new THREE.QuadraticBezierCurve3(p1, p2, p3);
二维三次贝塞尔曲线CubicBezierCurve
二维三次贝赛尔曲线,参数为四个二维向量对象
// p1、p4是曲线起始点,p2、p3是曲线的控制点
const p1 = new THREE.Vector2(-80, 0);
const p2 = new THREE.Vector2(-40, 50);
const p3 = new THREE.Vector2(50, 50);
const p4 = new THREE.Vector2(80, 0);
const curve = new THREE.CubicBezierCurve(p1, p2, p3, p4);
三维三次贝赛尔曲线CubicBezierCurve3
三维三次贝赛尔曲线,参数为四个三维向量对象
// p1、p4是曲线起始点,p2、p3是曲线的控制点
const p1 = new THREE.Vector3(-80, 0, 0);
const p2 = new THREE.Vector3(-40, 50, 0);
const p3 = new THREE.Vector3(50, 50, 0);
const p4 = new THREE.Vector3(80, 0, 100);
const curve = new THREE.CubicBezierCurve3(p1, p2, p3, p4);
不同贝塞尔曲线的区别
控制点会着影响贝塞尔曲线的高度,参数点为二维向量的曲线只能在某平面展示,参数点为三味向量则可在空间中展示
- 二维二次QuadraticBezierCurve :共有三个参数点,中间的那个为控制点,参数点为二维向量Vectoer2
- 三维二次QuadraticBezierCurve3 :共有三个参数点,中间的那个为控制点,参数点为三维向量Vectoer3
- 二维三次CubicBezierCurve :共有四个参数点,中间的两个点为控制点,参数点为二维向量Vectoer2
- 三维三次CubicBezierCurve3 :共有四个参数点,中间的两个点为控制点,参数点为三维向量Vectoer3
5. 组合曲线CurvePath
通过CurvePath对象,你可以将直线、圆弧、贝塞尔曲线等线条连接成一条直线。
直线线段LineCurve3和LineCurve
// LineCurve3线段的参数为三维向量对象
new THREE.LineCurve3(new THREE.Vector3(), new THREE.Vector3());
// LineCurve3线段的参数为二维向量对象
new THREE.LineCurve(new THREE.Vector2(), new THREE.Vector2());
下面创建二条直线和一条圆弧并将其使用CurvePath对象连接起来
const R = 80;//圆弧半径
const H = 200;//直线部分高度
// 直线1
const line1 = new THREE.LineCurve(new THREE.Vector2(R, H), new THREE.Vector2(R, 0));
// 圆弧
const arc = new THREE.ArcCurve(0, 0, R, 0, Math.PI, true);
// 直线2
const line2 = new THREE.LineCurve(new THREE.Vector2(-R, 0), new THREE.Vector2(-R, H));
// CurvePath创建一个组合曲线对象
const CurvePath = new THREE.CurvePath();
//line1, arc, line2拼接出来一个U型轮廓曲线,注意顺序
CurvePath.curves.push(line1, arc, line2);
6. 管道几何体TubeGeometry
管道几何体就是基于一个3D的曲线,生成一个管道几何体
构造函数格式:TubeGeometry(path, tubularSegments, radius, radiusSegments, closed)
参数 | 值 |
path | 扫描路径,路径要用三维曲线 |
tubularSegments | 路径方向细分数,默认64 |
radius | 管道半径,默认1 |
radiusSegments | 管道圆弧细分数,默认8 |
closed | Boolean值,管道是否闭合 |
// 三维样条曲线
const path = new THREE.CatmullRomCurve3([
new THREE.Vector3(-50, 20, 90),
new THREE.Vector3(-10, 40, 40),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(60, -60, 0),
new THREE.Vector3(70, 0, 80)
]);
// path:路径 40:沿着轨迹细分数 2:管道半径 25:管道截面圆细分数
const geometry = new THREE.TubeGeometry(path, 40, 2, 25);
7. 车削几何体LatheGeometry
车削几何体可以利用一个2D轮廓,将其旋转成一个3D的几何体曲面
格式:LatheGeometry(points, segments, phiStart, phiLength)
points Vector2表示的坐标数据组成的数组
segments 圆周方向细分数,默认12
phiStart 开始角度,默认0
phiLength 旋转角度,默认2π
参数 | 值 |
points | Vector2表示的坐标数据组成的数组 |
segments | 圆周方向细分数,默认12 |
phiStart | 开始角度,默认0 |
phiLength | 旋转角度,默认2π |
// Vector2表示的三个点坐标,三个点构成的轮廓相当于两端直线相连接
const pointsArr = [
new THREE.Vector2(50, 60),
new THREE.Vector2(25, 0),
new THREE.Vector2(50, -60)
];
// LatheGeometry:pointsArr轮廓绕y轴旋转生成几何体曲面
// pointsArr:旋转几何体的旋转轮廓形状
const geometry = new THREE.LatheGeometry(pointsArr);
8. 轮廓几何体shapeGeometry
有些时候已知一个多边形的外轮廓坐标,想通过这些外轮廓坐标生成一个多边形几何体平面,这时候你可以借助threejs提供的轮廓填充shapeGeometry几何体实现。
// 一组二维向量表示一个多边形轮廓坐标
const pointsArr = [
new THREE.Vector2(-50, -50),
new THREE.Vector2(-60, 0),
new THREE.Vector2(0, 50),
new THREE.Vector2(60, 0),
new THREE.Vector2(50, -50),
]
// Shape表示一个平面多边形轮廓,参数是二维向量构成的数组pointsArr
const shape = new THREE.Shape(pointsArr);
// 创建轮廓几何体
const geometry = new THREE.ShapeGeometry(shape);
9. 拉伸ExtrudeGeometry
拉伸ExtrudeGeometry像轮廓几何体一样,都是基于一个平面轮廓shape进行变化,生成一个几何体,轮廓几何体是将形状对象shape显现出来,拉伸几何体将形状对象shape进行向下拉伸后的形状显现出来
// Shape表示一个平面多边形轮廓
const shape = new THREE.Shape([
// 按照特定顺序,依次书写多边形顶点坐标
new THREE.Vector2(-50, -50), //多边形起点
new THREE.Vector2(-50, 50),
new THREE.Vector2(50, 50),
new THREE.Vector2(50, -50),
]);
const geometry = new THREE.ExtrudeGeometry(
// 平面轮廓
shape,
{
depth: 20, // 拉伸长度
bevelThickness: 5, //倒角尺寸:拉伸方向
bevelSize: 5, //倒角尺寸:垂直拉伸方向
bevelSegments: 20, //倒圆角:倒角细分精度,默认3
}
);
10. 扫描ExtrudeGeometry
通过ExtrudeGeometry除了可以实现将形状Shape对象拉伸成型,还可以让一个形状Shape对象沿着一条曲线扫描成型。
// 扫描轮廓:Shape表示一个平面多边形轮廓
const shape = new THREE.Shape([
// 按照特定顺序,依次书写多边形顶点坐标
new THREE.Vector2(0,0), //多边形起点
new THREE.Vector2(0,10),
new THREE.Vector2(10,10),
new THREE.Vector2(10,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//沿着路径细分精度,越大越光滑
}
);
11. 多边形轮廓shape
多边形轮廓shape,是直接通过一组二维向量Vector2表示的xy点坐标创建
shape的父类是path,有以下方法
- .lineTo() 直线
- .arc() 圆弧
- .absarc() 绝对圆弧
- .splineThru() 二维样条曲线
- .bezierCurveTo() 二维三次贝塞尔曲线
- .quadraticCurveTo() 二维二次贝塞尔曲线
// Shape表示一个平面多边形轮廓
const shape = new THREE.Shape([
// 按照特定顺序,依次书写多边形顶点坐标
new THREE.Vector2(-50, -50), //多边形起点
new THREE.Vector2(-50, 50),
new THREE.Vector2(50, 50),
new THREE.Vector2(50, -50),
]);
.currentPoint属性
.currentPoint属性字面意思是当前点,默认值Vector2(0,0)。
// .currentPoint属性字面意思是当前点,默认值Vector2(0,0)。
const shape = new THREE.Shape();
console.log('currentPoint',shape.currentPoint)
.moveTo()方法
.moveTo()方法将改变.currentPoint属性
// .moveTo()方法可以改变当前currentPoint属性
const shape = new THREE.Shape();
shape.moveTo(10,0);
绘制直线.lineTo()
.lineTo()绘制直线线段,直线线段的起点是当前点属性.currentPoint表示的位置,结束点是.lineTo()的参数表示的坐标。
// .lineTo()绘制直线线段,直线线段的起点是当前点属性.currentPoint表示的位置,结束点是.lineTo()的参数表示的坐标。
const shape = new THREE.Shape();
//.currentPoint变为(10,0)
shape.moveTo(10,0);
// 绘制直线线段,起点(10,0),结束点(100,0)
shape.lineTo(100,0);
12. 多边形Shape(内孔)
有些多边形是有内孔的,这时候需要借助shape的.holes()来实现
// 创建shape,绘制一个矩形轮廓
const shape = new THREE.Shape();
// .lineTo(100, 0)绘制直线线段,线段起点:.currentPoint,线段结束点:(100,0)
shape.lineTo(100, 0);
shape.lineTo(100, 100);
shape.lineTo(0, 100)
// 创建Shape内孔的轮廓
const path1 = new THREE.Path();// 圆孔1
path1.absarc(20, 20, 10);
const path2 = new THREE.Path();// 圆孔2
path2.absarc(80, 20, 10);
const path3 = new THREE.Path();// 方形孔
path3.moveTo(50, 50);
path3.lineTo(80, 50);
path3.lineTo(80, 80);
path3.lineTo(50, 80);
// 将内孔轮廓添加到shape中
shape.holes.push(path1, path2,path3);
// 使用ExtrudeGeometry拉伸成长方体,方便观看内孔效果
const geometry = new THREE.ExtrudeGeometry(shape, {
depth:20,//拉伸长度
bevelEnabled:false,//禁止倒角
curveSegments:50,
});
13. 模型边界线EdgesGeometry
借助EdgesGeometry,可以展示出模型的边界线
const geometry = new THREE.BoxGeometry(50, 50, 50);
const material = new THREE.MeshLambertMaterial({
color: 0x004444,
transparent:true,
opacity:0.5,
});
const mesh = new THREE.Mesh(geometry, material);
// 长方体geometry作为EdgesGeometry参数创建一个新的几何体
const edges = new THREE.EdgesGeometry(geometry);
const edgesMaterial = new THREE.LineBasicMaterial({
color: 0x00ffff,
})
// 使用LineSegments将几何体边界线显示出来
const line = new THREE.LineSegments(edges, edgesMaterial);
mesh.add(line);
14. 曲线颜色渐变
通过几何体顶点颜色.attributes.color数据,可以实现曲线的渐变
//创建一个几何体对象
const geometry = new THREE.BufferGeometry();
// 三维样条曲线
const curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-50, 20, 90),
new THREE.Vector3(-10, 40, 40),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(60, -60, 0),
new THREE.Vector3(70, 0, 80)
]);
const pointsArr = curve.getSpacedPoints(100); //曲线取点
geometry.setFromPoints(pointsArr); //pointsArr赋值给顶点位置属性
const pos = geometry.attributes.position;
const count = pos.count; //顶点数量
// 计算每个顶点的颜色值
const colorsArr = [];
for (let i = 0; i < count; i++) {
const percent = i / count; //点索引值相对所有点数量的百分比
//根据顶点位置顺序大小设置颜色渐变
// 红色分量从0到1变化,蓝色分量从1到0变化
colorsArr.push(percent, 0, 1 - percent); //蓝色到红色渐变色
}
//类型数组创建顶点颜色color数据
const colors = new Float32Array(colorsArr);
// 设置几何体attributes属性的颜色color属性
geometry.attributes.color = new THREE.BufferAttribute(colors, 3);
const material = new THREE.LineBasicMaterial({
vertexColors: true, //使用顶点颜色渲染
});
const line = new THREE.Line(geometry, material);
15. Color颜色渐变插值
颜色渐变插值方法有.lerpColor()和.lerp(),他们功能是相同的,区别是使用的语法不一样
// lerpColors用法,percent是两颜色的混合百分比
.lerpColors(Color1,Color2, percent)
// lerp用法
const c1 = new THREE.Color(0xff0000); //红色
const c2 = new THREE.Color(0x0000ff); //蓝色
c1.lerp(c2, percent);
const geometry = new THREE.BufferGeometry(); //创建一个几何体对象
// 三维样条曲线
const curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-50, 20, 90),
new THREE.Vector3(-10, 40, 40),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(60, -60, 0),
new THREE.Vector3(70, 0, 80)
]);
const pointsArr = curve.getSpacedPoints(100); //曲线取点
geometry.setFromPoints(pointsArr); //pointsArr赋值给顶点位置属性
const pos = geometry.attributes.position;
const count = pos.count; //顶点数量
// 计算每个顶点的颜色值
const colorsArr = [];
// 根据顶点距离起点远近进行颜色插值计算
const c1 = new THREE.Color(0x00ffff); //曲线起点颜色 青色
const c2 = new THREE.Color(0xffff00); //曲线结束点颜色 黄色
for (let i = 0; i < count; i++) {
const percent = i / count; //点索引值相对所有点数量的百分比
//根据顶点位置顺序大小设置颜色渐变
const c = c1.clone().lerp(c2, percent);//颜色插值计算
colorsArr.push(c.r, c.g, c.b);
}
//类型数组创建顶点颜色color数据
const colors = new Float32Array(colorsArr);
// 设置几何体attributes属性的颜色color属性
geometry.attributes.color = new THREE.BufferAttribute(colors, 3);
const material = new THREE.LineBasicMaterial({
vertexColors: true, //使用顶点颜色渲染
});
const line = new THREE.Line(geometry, material);
文章中部分素材选取自Threejs中文网:Three.js中文网