本段内容会写在0篇以外所有的,本人所编写的Threejs教程中
对,学习ThreeJS有捷径
当你有哪个函数不懂的时候,第一时间去翻一翻文档
当你有哪个效果不会做的时候,第一时间去翻一翻所有的案例,也许就能找到你想要的效果
最重要的一点,就是,绝对不要怕问问题,越怕找找别人问题,你的问题就会被拖的越久
如果你确定要走WebGL/ThreeJS的开发者路线的话,以下行为可以让你更快的学习ThreeJS
在ThreeJS中,官方提供了大量的内置几何体,比如说我们前面的教程中使用到的,BoxGeometry,PlaneGeometry
今天就着重对这些几何体做一个基本介绍
所有几何体均在官网中有对应的文档,在官网左上角的搜索框内,搜索geometry即可
接下来,我们就按顺序,来介绍每一个几何体
前面都已经都用过很多次了,但是这一次会详细讲解
立方缓冲几何体属于比较常用的案例几何体
function addMesh(){
let geometry = new THREE.BoxGeometry(1,1,1,2,2,2);
let material = new THREE.MeshBasicMaterial({
color:"#ff0000",
wireframe:true
});
mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
}
我们这次在材质中添加了一个属性:wireframe:true,这个属性可以让geometry以点线面的形式被渲染出来
这里我们的boxGeometry增加了后三个参数,这三个参数用于决定在 width,height,depth三个面的boxGeometry分段数,分段数越高,构成这个box使用的点线面数量越多
如果和之前一样,不写后面三个参数的话,后面三个参数的默认值均为1的情况下,我们渲染出来的效果是这样的
分段数这个概念更多的是用于建模软件,当你拥有更多的点线面时,你就可以通过操作点线面来实现模型的变形操作,早期的threejs中,还使用着geometry的概念,geometry的概念中,就允许用户操作点线面来对图形进行变形操作
//该操作在最新版已失效
geometry.vecties[0].set(x,y,z);
新版本对应的操作:
geometry.attributes.position.array[0] = x;
geometry.attributes.position.array[1] = y;
geometry.attributes.position.array[2] = z;
两种操作方式的不同,是因为,在早期,threejs中存在一个类为 geometry,也同时存在一个类为bufferGeomtry,但是因为geometry会存在过多占用内存和算力的问题,这个类最终被废除了
而变形操作,无论是对新人还是老手来说,都是一个比较麻烦的操作,这种问题,一般交给建模师去处理就好,只有极少数情况下,需要你去将通用图形变形的时候,也许你能用到这种概念
分段数的其他用途,暂时笔者在开发中没有发现,所以这里不做太多讨论,如果在看博客的你有相关的想法的话,可以在本文下留言讨论
构造器:new BoxGeometry(width : Float, height : Float, depth : Float, widthSegments : Integer, heightSegments : Integer, depthSegments : Integer)
上述构造器只需要知道前三个属性长宽高即可,后面三个为分段数,分段数必须为整数
圆形缓冲几何体官方介绍
let geometry = new THREE.CircleGeometry( 1, 32 );
构造器:CircleGeometry(radius : Float, segments : Integer, thetaStart : Float, thetaLength : Float)
radius — 圆形的半径,默认值为1
segments — 分段(三角面)的数量,最小值为3,默认值为8。
thetaStart — 第一个分段的起始角度,默认为0。(three o’clock position)
thetaLength — 圆形扇区的中心角,通常被称为“θ”(西塔)。默认值是2*Pi,这使其成为一个完整的圆。
官方的这段介绍可能比较专业,以下为个人解释:
属性名 | 值类型 | 默认值 | 属性说明 |
---|---|---|---|
radius | Float | 1 | 半径,这个属性无需解释 |
segments | Integer | 8 | 构成圆形的三角面数量,这个与上方的boxGeometry的分段数有一定区别,如下图所示,这里的值越高,我们产生的正多边形就越接近于圆形,所以本质上这个函数创建的不是圆形而是正多边形,由segments来控制最终产生的正多边形的边的数量 |
thetaStart | float | 0 | 一般来说,我们都会有一个画圆的起始位置 |
thetaLength | float | 2π | 这里是指画笔沿着圆心画了多长的距离 |
比如说想要创建一个半圆,我们从0开始画,然后让画笔画到180度的位置停下
let geometry = new THREE.CircleGeometry(1, 24,0,Math.PI);
比如说想要创建一个倒半圆,我们从180度的位置开始画,然后画到360度(180 + 180)停下,这样就是一个下半圆
let geometry = new THREE.CircleGeometry(1, 24,Math.PI,Math.PI);
这种圆形适合做基础的饼状图,但是仅仅适合2D的饼状图,如果想要做3D的饼状图,可以选用下面的圆柱缓冲几何体
这里我们和官方的顺序做了调换,第四个再讲ConeGeometry(圆锥缓冲几何体)
let geometry = new THREE.CylinderGeometry(1, 1, 2, 32);
构造器:CylinderGeometry(radiusTop : Float, radiusBottom : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float)
radiusTop — 圆柱的顶部半径,默认值是1。
radiusBottom — 圆柱的底部半径,默认值是1。
height — 圆柱的高度,默认值是1。
radialSegments — 圆柱侧面周围的分段数,默认为8。
heightSegments — 圆柱侧面沿着其高度的分段数,默认值为1。
openEnded — 一个Boolean值,指明该圆锥的底面是开放的还是封顶的。默认值为false,即其底面默认是封顶的。
thetaStart — 第一个分段的起始角度,默认为0。(three o’clock position)
thetaLength — 圆柱底面圆扇区的中心角,通常被称为“θ”(西塔)。默认值是2*Pi,这使其成为一个完整的圆柱。
圆柱高度就不解释了
openEnded设置为true时,会创建一个圆型管而不是一个圆柱
比起圆来说,圆柱更适合用于做饼状图,下面是一种饼状图演示
function addMesh(){
let geometry1 = new THREE.CylinderGeometry(1, 1, 1, 32,1,false,0,Math.PI * 0.2);
let material1 = new THREE.MeshStandardMaterial({color:"#ff0000"});
let mesh1 = new THREE.Mesh(geometry1,material1);
scene.add(mesh1);
let geometry2 = new THREE.CylinderGeometry(1, 1, 1, 32,1,false,Math.PI * 0.2,Math.PI * 0.4);
let material2 = new THREE.MeshStandardMaterial({color:"#8eff63"});
let mesh2 = new THREE.Mesh(geometry2,material2);
scene.add(mesh2);
let geometry3 = new THREE.CylinderGeometry(1, 1, 1, 32,1,false,Math.PI * 0.6,Math.PI * 0.6);
let material3 = new THREE.MeshStandardMaterial({color:"#1f99ff"});
let mesh3 = new THREE.Mesh(geometry3,material3);
scene.add(mesh3);
let geometry4 = new THREE.CylinderGeometry(1, 1, 1, 32,1,false,Math.PI * 1.2,Math.PI * 0.8);
let material4 = new THREE.MeshStandardMaterial({color:"#ff00e5"});
let mesh4 = new THREE.Mesh(geometry4,material4);
scene.add(mesh4);
}
这里对代码就不做详细解释了,只要搞明白绘制起点,绘制多少角度的概念后,理解这个饼状图应该不会太难
当我们看了3个Wireframe效果下的模型后,我们发现,图形上有很多个三角形,这个就是我们的三角面,在threejs中,所有的几何体,都是由一个个三角面构成,市面上常见的两种构成模型的方式,一种是使用三角面,一种是使用平行四边形
具体的三角面构成模型的原理,将在后续的BufferGeometry中提到
如果已经提前学习了WebGL的话,后续在学习BufferGeometry原理时,学习难度会相应降低很多
圆锥缓冲几何体几乎和上面圆柱的构造器一致,唯一区别就是这里只需要传入下底面的半径即可
构造器
ConeGeometry(radius : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float)
radius — 圆锥底部的半径,默认值为1。
height — 圆锥的高度,默认值为1。
radialSegments — 圆锥侧面周围的分段数,默认为8。
heightSegments — 圆锥侧面沿着其高度的分段数,默认值为1。
openEnded — 一个Boolean值,指明该圆锥的底面是开放的还是封顶的。默认值为false,即其底面默认是封顶的。
thetaStart — 第一个分段的起始角度,默认为0。(three o’clock position)
thetaLength — 圆锥底面圆扇区的中心角,通常被称为“θ”(西塔)。默认值是2*Pi,这使其成为一个完整的圆锥。
let geometry = new THREE.ConeGeometry(0.5,2,16,1);
圆锥可以单独使用做成3D箭头,也可以搭配一个圆柱体做成一个高级3D箭头
function addMesh(){
let geometry = new THREE.ConeGeometry(0.5,2,16,1);
let material = new THREE.MeshStandardMaterial({color:"#ff0000"});
let mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
let geometry2 = new THREE.CylinderGeometry(0.35,0.35,2,16,1).translate(0,-2,0);
let material2 = new THREE.MeshStandardMaterial({color:"#ff0000"});
let mesh2 = new THREE.Mesh(geometry2,material2);
scene.add(mesh2);
}
箭头这里就仅做一个介绍,后续将会单独开一篇博客来讲解如何制作一个可以指向目标的箭头
边缘几何体本质上是一个辅助对象,用于查看geometry的边缘
构造器
EdgesGeometry( geometry : BufferGeometry, thresholdAngle : Integer )
geometry — 任何一个几何体对象。
thresholdAngle — 仅当相邻面的法线之间的角度(单位为角度)超过这个值时,才会渲染边缘。默认值为1。
该几何体在后续加载模型的章节中会提到
讲这个之前,就要先讲Shape
shape的官方文档
你可以使用Shape绘制出任何你想要的图形,但是,需要你一个坐标点一个坐标点的去输入你的绘制路径
然后使用创建好的Shape,来创建ShapeGeometry
let x = 0, y = 0;
let heartShape = new THREE.Shape();
heartShape.moveTo( x + 5, y + 5 );
heartShape.bezierCurveTo( x + 5, y + 5, x + 4, y, x, y );
heartShape.bezierCurveTo( x - 6, y, x - 6, y + 7,x - 6, y + 7 );
heartShape.bezierCurveTo( x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19 );
heartShape.bezierCurveTo( x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7 );
heartShape.bezierCurveTo( x + 16, y + 7, x + 16, y, x + 10, y );
heartShape.bezierCurveTo( x + 7, y, x + 5, y + 5, x + 5, y + 5 );
let geometry = new THREE.ShapeGeometry( heartShape );
let material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
let mesh = new THREE.Mesh( geometry, material ) ;
scene.add( mesh );
shape相当于绘制好的图形,shapeGeometry才是能显示出来的几何体
shapeGeometry用于创建一些比较容易创建的简单几何体,比如上面的心形,当你使用其他的geometry无法创建那些图形时,可以考虑使用ShapeGeometry
挤压几何体可以理解为3D的ShapeGeometry,也是需要使用Shape来创建
将上面new ShapeGeometry,换成new ExtrudeGeometry,就出现了下面的效果
挤压几何体常用于使用Shape生成3D的柱状体
该几何体为extrudeGeometry的子类,后续在讲添加3D文字时会讲到
构造器:SphereGeometry(radius : Float, widthSegments : Integer, heightSegments : Integer, phiStart : Float, phiLength : Float, thetaStart : Float, thetaLength : Float)
radius — 球体半径,默认为1。
widthSegments — 水平分段数(沿着经线分段),最小值为3,默认值为32。
heightSegments — 垂直分段数(沿着纬线分段),最小值为2,默认值为16。
phiStart — 指定水平(经线)起始角度,默认值为0。。
phiLength — 指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2。
thetaStart — 指定垂直(纬线)起始角度,默认值为0。
thetaLength — 指定垂直(纬线)扫描角度大小,默认值为 Math.PI。
该几何体是通过扫描并计算围绕着Y轴(水平扫描)和X轴(垂直扫描)的顶点来创建的。 因此,不完整的球体(类似球形切片)可以通过为phiStart,phiLength,thetaStart和thetaLength设置不同的值来创建, 以定义我们开始(或结束)计算这些顶点的起点(或终点)。
当你能理解上面圆形的构造器时,球的构造器也无需过多的解释,分段数越高,球体圆滑程度越高,想要制作半球的话,可以通过改变经线纬线的初始位置,与绘制角度来制作
球体能做的东西可就太多了,比如说我们常见的地球,太阳,灯泡等,只要是个球体或者半球体的物体,均可以使用它来做
后续会有专门一篇博客来介绍如何制作一个地球
关于这个几何体,将在后续写曲线与路径的时候会做讲解,本篇仅提一下名字
构造器:WireframeGeometry( geometry : BufferGeometry )
geometry — 任意几何体对象。
网格几何体其实是制作线框效果的另一种方式
网格几何体实际上是一种线构成的图形,它与材质中的wireframe的区别是,一种是使用geometry的方式,就是演员本身就是线条装,而wireframe则是让演员披上了透明到你只能看到线条的衣服,如果你在之前学习过WebGL底层,对这个理解起来会更容易
以下几何体均在笔者的开发与学习中从未使用过,仅建议去官网了解一下即可,有兴趣的可以写几个案例试试看
官方解释为:多面体在三维空间中具有一些平面的立体图形。这个类将一个顶点数组投射到一个球面上,之后将它们细分为所需的细节级别。 这个类由DodecahedronGeometry、IcosahedronGeometry、OctahedronGeometry和TetrahedronGeometry 所使用,以生成它们各自的几何结构。
该几何体是下面几个几何体的超类,不建议直接使用
十二面缓冲几何体DodecahedronGeometry
二十面缓冲几何体IcosahedronGeometry
八面缓冲几何体OctahedronGeometry
四面缓冲几何体TetrahedronGeometry
上述四种几何体均可以通过调整参数让它无限接近于球体,其他用途暂时笔者在开发中未发现
车削缓冲几何体更适合在建模软件中使用,用于快速创建花瓶,碗碟之类的,中心对称的物体,上面提到的箭头也可以使用车削缓冲几何体来创建
二维圆环笔者也没有找到实际用途
三位圆环可以用于制作轮胎,手镯等物体,但是笔者在开发中从未使用
这个几何体是官方案例中登场最多的几何体,笔者认为它是一种最适合写案例的几何体