Three.js-硬要自学系列15 (圆弧顶点、几何体方法、曲线简介、圆、椭圆、样条曲线、贝塞尔曲线)

本章主要学习知识点

  • 学习如何生成圆弧
  • 了解立方体和直线之间的关系
  • 了解曲线的基本概念
  • 使用曲线在场景中创建圆和椭圆
  • 了解什么是样条曲线,并使用样条曲线绘制不同的线条
  • 使用贝塞尔曲线创建线条

生成圆弧顶点

通过顶点生成圆弧,首先要选定圆心和半径,确定要生成的顶点数量,这决定了圆弧的平滑程度

js 复制代码
// 设置圆心坐标
const cx = 5;
const cy = 5;
const R = 10; // 圆的半径
const N = 100;  // 顶点数量
const sp = 2*Math.PI / N;   // 每个顶点之间的弧度

这里设置顶点数为100,要如何获取到每个顶点的坐标呢,可以通过三角函数计算出每个顶点的坐标

js 复制代码
const arr = [];
for (let i = 0; i <= N; i++) {
    const angle = sp*i;
    const x = cx+ R * Math.cos(angle)   
    const y = cy+ R * Math.sin(angle)   
    arr.push(x,y, 0)
}

设置几何体的顶点,通过使用LineLoop连接各个顶点

js 复制代码
geometry.setAttribute('position', new THREE.Float32BufferAttribute(arr, 3))

const material = new THREE.LineBasicMaterial({
    color: 'deepskyblue'
})
const line = new THREE.LineLoop(geometry, material)
scene.add(line)

调整cxcy圆心值,我们可以任意移动该圆弧

几何体方法

还记的在BufferGeometry那一章节,通过设置顶点坐标,我们绘制了一个矩形平面吗,这里我们使用setFromPoints快速设置顶点,然后使用Line方法来进行连接,看看效果如何

js 复制代码
const geometry = new THREE.BufferGeometry()
const pointsArr = [
  // 三维向量Vector3表示的坐标值
  new THREE.Vector3(0,0,0),
  new THREE.Vector3(0,3,0),
  new THREE.Vector3(0,3,3),
  new THREE.Vector3(0,0,3),
];
geometry.setFromPoints(pointsArr); // 设置顶点
const material = new THREE.LineBasicMaterial({color: 'deepskyblue'})
const line = new THREE.Line(geometry,material)
scene.add(line)

曲线简介

曲线是生成3D路径的核心工具,可以理解为"用数学公式自动画线"。

常见曲线类型

  • 基础圆弧曲线 ArcCurve

用来画标准圆弧,如车轮、钟表刻度等,其核心参数为:圆心半径起始/结束角度

  • 椭圆曲线 EllipseCurve

用来绘制椭圆或椭圆弧,如行星轨道, 其核心参数为:X轴半径Y轴半径

  • 贝塞尔曲线 CubicBezierCurve3

用于创建平滑的复杂曲线,如心形、波浪等,其核心参数为:起点两个锚点终点

  • 样条曲线 CatmullRomCurve3

用于通过多个点生成平滑路径,如管道、流动轨迹,相机漫游等

实践上手下

通过EllipseCurve创建一个椭圆曲线,并获取曲线上的顶点,这里获取了曲线上100个顶点坐标

js 复制代码
const arc = new THREE.EllipseCurve(0,0,10,5)
// const pointsArr = arc.getSpacedPoints(100)  // 等间距
const pointsArr = arc.getPoints(100)  // 非等间距

设置几何体的顶点,并使用点模型呈现,效果如下

js 复制代码
const geometry = new THREE.BufferGeometry().setFromPoints(pointsArr)
const material = new THREE.PointsMaterial({color: 'skyblue',size: 0.2})
const line = new THREE.Points(geometry,material)
scene.add(line)

圆、椭圆

通过使用ArcCurve生成圆弧,当x/y轴半径相同时就是圆。

椭圆

通过使用EllipseCurve生成椭圆,当x/y轴半径不同时就是椭圆

创建一个圆弧

JS 复制代码
  const arcCurve = new THREE.ArcCurve(0,0,5,0,Math.PI/4 )
  const points = arcCurve.getPoints(100)
  const geometry = new THREE.BufferGeometry().setFromPoints(points)
  const material = new THREE.LineBasicMaterial({color: 'deeppink'})
  const ellipse = new THREE.Line(geometry,material)
  scene.add(ellipse)

样条曲线

样条曲线(Spline Curve) 是一种通过多个控制点自动生成平滑路径的工具,可以理解为"用一系列坐标点自动画出一条自然流畅的曲线"。

创建三维样条曲线

样条曲线至少需要2个控制点,但通常建议4个或4个以上点效果会比较好

js 复制代码
const arr = [
  new THREE.Vector3(-5, 2, 9),
  new THREE.Vector3(-1, 4, 4),
  new THREE.Vector3(0, 0, 0),
  new THREE.Vector3(6, -6, 0),
  new THREE.Vector3(7, 0, 8)
]
// 三维样条曲线
const curve = new THREE.CatmullRomCurve3(arr)
// 创建样条曲线
const geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(50))
const material = new THREE.PointsMaterial({ color: 'skyblue' ,size: 0.1})
const curveObject = new THREE.Points(geometry, material)
// 将模型添加至场景中
scene.add(curveObject)

创建二维样条曲线

所谓的二维,即曲线始终是在一个平面上绘制

js 复制代码
const curve= new THREE.SplineCurve(arr);
// 创建一个BufferGeometry对象,并设置其顶点为curve.getPoints(100)返回的数组
const geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(100))
const material = new THREE.LineBasicMaterial({
    color: 'deepskyblue'
})
const curveObject = new THREE.Line(geometry, material)
scene.add(curveObject)

物体沿曲线运动

通过不断修改小球的位置来实现小球沿着曲线运动

js 复制代码
function animation() {
    t += 0.001; // 时间递增
    if (t >= 1) { // 当时间超过1时,重置为0
        t = 0;
    }
    const index = Math.floor(t % 1 * 100); // 计算当前点的索引
    mesh.position.copy(points[index]); // 将mesh的位置设置为当前点的位置
  // 渲染场景和相机
  renderer.render( scene, camera );
  requestAnimationFrame( animation );
}

贝塞尔曲线

贝塞尔曲线是一种通过控制点生成平滑曲线的数学工具,可以理解为「用几个关键点自动画出复杂曲线」。

贝塞尔曲线的类型

  • 二次贝塞尔曲线 QuadraticBezierCurve

    • 控制点数量: 1个控制点
    • 适用场景:简单曲线,如抛物线、水滴形状等
  • 三次贝塞尔曲线 CubicBezierCurve

    • 控制点数量: 2个控制点
    • 适用场景:复杂曲线、如心形、波浪线等

二维二次贝塞尔

js 复制代码
const p1 = new THREE.Vector2(-8, 0);
const p2 = new THREE.Vector2(2, 10);
const p3 = new THREE.Vector2(8, 0);

const curve = new THREE.QuadraticBezierCurve(p1,p2,p3)
const pointsArr = curve.getPoints(100)
const geometry = new  THREE.BufferGeometry();
geometry.setFromPoints(pointsArr)
const material = new THREE.LineBasicMaterial({color: 'skyblue'})
const material2 = new THREE.PointsMaterial({color: 'green', size: 0.1})
const curveObject = new THREE.Line(geometry, material)
const pointObject = new THREE.Points(geometry, material2)
scene.add(curveObject, pointObject)

三维三次贝塞尔

js 复制代码
const p1 = new THREE.Vector3(-8, 0, 0);
const p2 = new THREE.Vector3(-4, 5, 0);
const p3 = new THREE.Vector3(15, 3, 0);
const p4 = new THREE.Vector3(8, 0, -3);
// 创建一个三次贝塞尔曲线,参数为四个点p1,p2,p3,p4
const curve = new THREE.CubicBezierCurve3(p1,p2,p3,p4)
const pointsArr = curve.getPoints(100)
// 创建一个BufferGeometry对象
const geometry = new  THREE.BufferGeometry();
// 将pointsArr数组中的点设置为几何体的顶点
geometry.setFromPoints(pointsArr)
const material = new THREE.LineBasicMaterial({color: 'skyblue'})
const curveObject = new THREE.Line(geometry, material)
scene.add(curveObject)

以上案例均可在案例中心查看体验

THREE 案例中心

相关推荐
zyk_5202 分钟前
前端渲染pdf文件解决方案-pdf.js
前端·javascript·pdf
Apifox.9 分钟前
Apifox 4月更新|Apifox在线文档支持LLMs.txt、评论支持使用@提及成员、支持为团队配置「IP 允许访问名单」
前端·人工智能·后端·ai·ai编程
划水不带桨15 分钟前
大数据去重
前端
沉迷...20 分钟前
手动实现legend 与 echarts图交互 通过js事件实现图标某项的高亮 显示与隐藏
前端·javascript·echarts
可观测性用观测云35 分钟前
观测云数据在Grafana展示的最佳实践
前端
uwvwko1 小时前
ctfhow——web入门214~218(时间盲注开始)
前端·数据库·mysql·ctf
Json____1 小时前
使用vue2开发一个医疗预约挂号平台-前端静态网站项目练习
前端·vue2·网站模板·静态网站·项目练习·挂号系统
HuaHua的世界1 小时前
说说 Vue 中 CSS scoped 的原理?
css·vue.js
littleplayer1 小时前
iOS Swift Redux 架构详解
前端·设计模式·架构
工呈士1 小时前
HTML 模板技术与服务端渲染
前端·html