
三维场景Scene
可以把三维场景Scene对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。
物体形状:几何体Geometry
https://threejs.org/manual/#zh/primitives
具体自带的API可以查询
Three.js提供了各种各样的几何体API,用来表示三维物体的几何形状。

文档搜索关键词geometry你可以看到threejs提供各种几何体相关API,具体使用方法,也可以参考文档。
//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(100, 100, 100); Geometry 长方体设置
const width = 7.1;
const height = 8;
const depth = 8;
const widthSegments = 8;
const heightSegments = 8;
const depthSegments = 10;
const geometry = new THREE.BoxGeometry(
width, height, depth,
widthSegments, heightSegments, depthSegments );
CircleGeometry 平面圆

const radius = 7;
const segments = 24;
const thetaStart = Math.PI * 0.00;
const thetaLength = Math.PI * 0.32;
const geometry = new THREE.CircleGeometry(
radius, segments, thetaStart, thetaLength );
// thetaStart 默认值为0 thetaLength默认值为2piConeGeometry 锥形

const radius = 4.0; // 锥形底部圆形大小
const height = 7.1; // 锥形高
const radialSegments = 20; // 锥形侧面边长
const geometry = new THREE.ConeGeometry( radius, height, radialSegments );
const radius = 6;
const height = 8;
const radialSegments = 17; // 底部圆线的数量(侧边线长数)
const heightSegments = 5; // 侧边垂直方向线的数量
const openEnded = false; // 底部圆是否显示
const thetaStart = Math.PI * 0.25;
const thetaLength = Math.PI * 1.52;
// thetaStart 默认值为0 thetaLength默认值为2pi 扇形的边框
const geometry = new THREE.ConeGeometry(
radius, height,
radialSegments, heightSegments,
openEnded,
thetaStart, thetaLength );物体外观:材质Material
如果你想定义物体的外观效果,比如颜色,就需要通过材质Material相关的API实现。
threejs不同材质渲染效果不同,下面就以threejs最简单的网格基础材质MeshBasicMaterial(opens new window)为例给大家实现一个红色材质效果。

//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial({
color: 0xff0000,//0xff0000设置材质颜色为红色
});
物体:网格模型Mesh
实际生活中有各种各样的物体,在threejs中可以通过网格模型Mesh(opens new window)表示一个虚拟的物体,比如一个箱子、一个鼠标。
// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
模型位置.position
实际生活中,一个物体往往是有位置的,对于threejs而言也是一样的,你可以通过位置属性.position定义网格模型Mesh在三维场景Scene中的位置。
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(0,10,0);
.add()方法
在threejs中你创建了一个表示物体的虚拟对象Mesh,需要通过.add()方法,把网格模型mesh添加到三维场景scene中。
scene.add(mesh);
透视投影相机PerspectiveCamera
Threejs提供了正投影相机OrthographicCamera(opens new window)和透视投影相机PerspectiveCamera(opens new window)。
透视投影相机PerspectiveCamera本质上就是在模拟人眼观察这个世界的规律。
// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera();
gui
// 实例化一个gui对象
const gui = new GUI();
//改变交互界面style属性
gui.domElement.style.right = '0px';
gui.domElement.style.width = '300px';
//创建一个对象,对象属性的值可以被GUI库创建的交互界面改变
const obj = {
x: 30,
};
// gui增加交互界面,用来改变obj对应属性
gui.add(obj, 'x', 0, 100);
// .add()创建的交互界面,会默认显示所改变属性的名字,为了通过交互界面更好理解你改变的某个对象属性,你可以通过.name()方法改变gui生成交互界面显示的内容。
const gui = new GUI();//创建GUI对象
gui.add(ambient, 'intensity', 0, 2.0).name('环境光强度');
gui.add(directionalLight, 'intensity', 0, 2.0).name('平行光强度');
// 步长.step()方法可以设置交互界面每次改变属性值间隔是多少。
gui.add(ambient, 'intensity', 0, 2.0).name('环境光强度').step(0.1);
// 当gui界面某个值的时候,.onChange()方法就会执行,这时候你可以根据需要通过.onChange()执行某些代码。
const obj = {
x: 30,
};
// 当obj的x属性变化的时候,就把此时obj.x的值value赋值给mesh的x坐标
gui.add(obj, 'x', 0, 180).onChange(function(value){
mesh.position.x = value;
// 你可以写任何你想跟着obj.x同步变化的代码
// 比如mesh.position.y = value;
});
// .addColor()生成颜色值改变的交互界面
const obj = {
color:0x00ffff,
};
// .addColor()生成颜色值改变的交互界面
gui.addColor(obj, 'color').onChange(function(value){
mesh.material.color.set(value);
});
.add()方法参数3和4数据类型:数字
格式:add(控制对象,对象具体属性,其他参数)
其他参数,可以一个或多个,数据类型也可以不同,gui会自动根据参数形式,自动生成对应的交互界面。
参数3和参数4,分别是一个数字,交互界面是一个鼠标可以拖动的拖动条,可以在一个区间改变属性的值
// 参数3、参数4数据类型:数字(拖动条)
gui.add(obj, 'x', 0, 180).onChange(function (value) {
mesh.position.x = value;
});.add()方法参数3数据类型:数组
参数3是一个数组,生成交互界面是下拉菜单
const obj = {
scale: 0,
};
// 参数3数据类型:数组(下拉菜单)
gui.add(obj, 'scale', [-100, 0, 100]).name('y坐标').onChange(function (value) {
mesh.position.y = value;
});.add()方法参数3数据类型:对象
参数3是一个对象,生成交互界面是下拉菜单
const obj = {
scale: 0,
};
// 参数3数据类型:对象(下拉菜单)
gui.add(obj, 'scale', {
left: -100,
center: 0,
right: 100
// 左: -100,//可以用中文
// 中: 0,
// 右: 100
}).name('位置选择').onChange(function (value) {
mesh.position.x = value;
});
.add()方法对应属性的数据类型:布尔值
如果.add()改变属性的对应的数据类型如果是布尔值,那么交互界面就是一个单选框。
const obj = {
bool: false,
};
// 改变的obj属性数据类型是布尔值,交互界面是单选框
gui.add(obj, 'bool').name('是否旋转');gui.add(obj, 'bool').onChange(function (value) {
// 点击单选框,控制台打印obj.bool变化
console.log('obj.bool',value);
});当GUI交互界面需要控制的属性比较多的时候,为了避免混合,可以适当分组管理,这样更清晰。
gui交互界面不分组
gui交互界面不分组,只有一个默认的总的菜单。
const gui = new GUI(); //创建GUI对象
//创建一个对象,对象属性的值可以被GUI库创建的交互界面改变
const obj = {
color: 0x00ffff,// 材质颜色
specular: 0x111111,// 材质高光颜色
};
// 材质颜色color
gui.addColor(obj, 'color').onChange(function(value){
material.color.set(value);
});
// 材质高光颜色specular
gui.addColor(obj, 'specular').onChange(function(value){
material.specular.set(value);
});
// 环境光强度
gui.add(ambient, 'intensity',0,2);
// 平行光强度
gui.add(directionalLight, 'intensity',0,2);
// 平行光位置
gui.add(directionalLight.position, 'x',-400,400);
gui.add(directionalLight.position, 'y',-400,400);
gui.add(directionalLight.position, 'z',-400,400);.addFolder()分组
new GUI()实例化一个gui对象,默认创建一个总的菜单,通过gui对象的.addFolder()方法可以创建一个子菜单,当你通过GUI控制的属性比较多的时候,可以使用.addFolder()进行分组。
.addFolder()返回的子文件夹对象,同样具有gui对象的.add()、.onChange()、.addColor()等等属性。
const gui = new GUI(); //创建GUI对象
const obj = {
color: 0x00ffff,// 材质颜色
};
// 创建材质子菜单
const matFolder = gui.addFolder('材质');
matFolder.close();
// 材质颜色color
matFolder.addColor(obj, 'color').onChange(function(value){
material.color.set(value);
});
// 材质高光颜色specular
matFolder.addColor(obj, 'specular').onChange(function(value){
material.specular.set(value);
});
// 环境光子菜单
const ambientFolder = gui.addFolder('环境光');
// 环境光强度
ambientFolder.add(ambient, 'intensity',0,2);
// 平行光强度
dirFolder.add(directionalLight, 'intensity',0,2);
// 平行光位置
dirFolder.add(directionalLight.position, 'x',-400,400);
dirFolder.add(directionalLight.position, 'y',-400,400);
dirFolder.add(directionalLight.position, 'z',-400,400);
关闭.close()和展开.open()交互界面
gui对象创建的总菜单或gui.addFolder()创建的子菜单都可以用代码控制交互界面关闭或开展状态。
const gui = new GUI(); //创建GUI对象
gui.close();//关闭菜单// 创建材质子菜单
const matFolder = gui.addFolder('材质');
matFolder.close();//关闭菜单.addFolder()套娃——子菜单嵌套子菜单
.addFolder()创建的对象,同样也具有.addFolder()属性,可以继续嵌套子菜单
// 平行光子菜单
const dirFolder = gui.addFolder('平行光');
dirFolder.close();//关闭菜单
// 平行光强度
dirFolder.add(directionalLight, 'intensity',0,2);
const dirFolder2 = dirFolder.addFolder('位置');//子菜单的子菜单
dirFolder2.close();//关闭菜单
// 平行光位置
dirFolder2.add(directionalLight.position, 'x',-400,400);
dirFolder2.add(directionalLight.position, 'y',-400,400);
dirFolder2.add(directionalLight.position, 'z',-400,400);针集合体的操作
// 几何体xyz三个方向都放大2倍
geometry.scale(2, 2, 2);
// 几何体沿着x轴平移50
geometry.translate(50, 0, 0);
// 几何体绕着x轴旋转45度
geometry.rotateX(Math.PI / 4);
// 几何体旋转、缩放或平移之后,查看几何体顶点位置坐标的变化
// BufferGeometry的旋转、缩放、平移等方法本质上就是改变顶点的位置坐标
console.log('顶点位置数据', geometry.attributes.position);
针对Mesh的操作

通过模型位置属性.position可以设置模型在场景Scene中的位置。模型位置.position的默认值是THREE.Vector3(0.0,0.0,0.0),表示坐标原点。
mesh.position.y = 80;mesh.position.set(80,2,10);平移
执行.translateX()、.translateY()等方法本质上改变的都是模型的位置属性.position。
网格模型沿着x轴正方向平移100,可以多次执行该语句,每次执行都是相对上一次的位置进行平移变换。
// 等价于mesh.position = mesh.position + 100;
mesh.translateX(100);//沿着x轴正方向平移距离100沿着Z轴负方向平移距离50。
mesh.translateZ(-50);沿着自定义的方向移动。
//向量Vector3对象表示方向
const axis = new THREE.Vector3(1, 1, 1);
axis.normalize(); //向量归一化
//沿着axis轴表示方向平移100
mesh.translateOnAxis(axis, 100);缩放
属性.scale表示模型对象的xyz三个方向上的缩放比例,.scale的属性值是一个三维向量对象Vector3,默认值是THREE.Vector3(1.0,1.0,1.0)。
x轴方向放大2倍
mesh.scale.x = 2.0;网格模型xyz方向分别缩放0.5,1.5,2倍
mesh.scale.set(0.5, 1.5, 2)克隆.clone()和复制.copy()
克隆.clone()、复制.copy()是threejs很多对象都具有的方法,比如三维向量对象Vector3、网格模型Mesh、几何体、材质。
克隆.clone()
克隆.clone()简单说就是复制一个和原对象一样的新对象,下面以三维向量对象Vector3给大家举例,其他的threejs对象都可以参照类似的写法。
const v1 = new THREE.Vector3(1, 2, 3);
console.log('v1',v1);
//v2是一个新的Vector3对象,和v1的.x、.y、.z属性值一样
const v2 = v1.clone();
console.log('v2',v2);复制.copy()
复制.copy()简单说就是把一个对象属性的属性值赋值给另一个对象,下面以三维向量对象Vector3给大家举例,其他的threejs对象都可以参照类似的写法。
const v1 = new THREE.Vector3(1, 2, 3);
const v3 = new THREE.Vector3(4, 5, 6);
//读取v1.x、v1.y、v1.z的赋值给v3.x、v3.y、v3.z
v3.copy(v1);Mesh克隆.clone()
通过mesh克隆.clone()一个和mesh一样的新模型对象mesh2。
const mesh2 = mesh.clone();
mesh2.position.x = 100;通过克隆.clone()获得的新模型和原来的模型共享材质和几何体
// 改变材质颜色,或者说改变mesh2颜色,mesh和mesh2颜色都会改变
// material.color.set(0xffff00);
mesh2.material.color.set(0xffff00);几何体和材质克隆.clone()
const mesh2 = mesh.clone();
// 克隆几何体和材质,重新设置mesh2的材质和几何体属性
mesh2.geometry = mesh.geometry.clone();
mesh2.material = mesh.material.clone();
// 改变mesh2颜色,不会改变mesh的颜色
mesh2.material.color.set(0xff0000);threejs应用程序的结构
