three.js
专业名词
场景(Scene)、相机(camera)和渲染器(WebGLRenderer)
render(scene, camera);
光源(light), 平行光, 点光源, 聚光光源
物体(object): 矢量(Vector3),形状(geometry),材质(material)
PerspectiveCamera(透视摄像机)。视野角度(FOV),长宽比(aspect ratio),远剪切面,近剪切面
网格(mesh)
Line(geometry, material);
scene.add(line);
左手坐标系
library
library name | function | describe |
---|---|---|
three.js | Three.js引擎 | |
Detector.js | 探测器 | 检测当前浏览器是否支持或者开启了WEBGL |
Stats.js | JavaScript性能监控器 | 监测动画效果 |
OrbitControls.js | 鼠标控制旋转的js | |
WindowResize.js | 处理窗口大小调整 | 在调整窗口的大小时更新渲染和相机 |
TransformControls.js | 鼠标操控物体移动、缩放、旋转的控件(物体操作工具) | |
EditorControls.js | 鼠标操控场景视角(即场景Camera位置),模拟实现平移整个场景的控件(场景控制工具) | |
dat.gui.js | 用于创建菜单栏 | 提供场景中的各个参数编辑功能(调试场景利器) |
资料
总结
代码片段
THREEx.WindowResize(renderer, camera); // 处理窗口大小调整。
controls = new THREE.OrbitControls( camera, renderer.domElement ); // 鼠标控制旋转
添加二维网格
var gridHelper = new THREE.GridHelper(1000, 20);
scene.add(gridHelper);
绘制三维网格
var gridXZ = new THREE.GridHelper(80, 10, 0xEED5B7, 0xEED5B7);
gridXZ.position.set( 80,0,80 );
this.mesh.add(gridXZ);
var gridXY = new THREE.GridHelper(80, 10, 0xEED5B7, 0xEED5B7);
gridXY.position.set( 80,80,0 );
gridXY.rotation.x = Math.PI/2;
this.mesh.add(gridXY);
var gridYZ = new THREE.GridHelper(80, 10, 0xEED5B7, 0xEED5B7);
gridYZ.position.set( 0,80,80 );
gridYZ.rotation.z = Math.PI/2;
this.mesh.add(gridYZ);
绘制直线
var linematerial = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors, linewidth: 1.3} );
var color1 = new THREE.Color( 0x000000 ), color2 = new THREE.Color( 0x000000 );
var p1 = new THREE.Vector3( 0, 0, 0 );
var p2 = new THREE.Vector3( 0, 0, 160 );
var geometry = new THREE.Geometry();
geometry.vertices.push(p1);
geometry.vertices.push(p2);
geometry.colors.push( color1, color2 );
var line = new THREE.Line( geometry, linematerial, THREE.LinePieces );
this.mesh.add(line);
添加物体
this.mesh = new THREE.Object3D();//忘了强调,这句话要放在所有的this.mesh.add()之前
var geometry = new THREE.SphereGeometry( 0.3, 32, 16 );
var material = new THREE.MeshLambertMaterial( { color: 0x00ff00 } );
meshpoint = new THREE.Mesh( geometry, material );
meshpoint.position.set(40,40,40);
this.mesh.add(meshpoint);
根据浏览器大小调整渲染器大小
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
开启鼠标控制
需要引入鼠标控制插件
// <script src="js/controls/OrbitControls.js"></script>
const controls = new THREE.OrbitControls(camera, renderer.domElement)
controls.enableDamping = true; // 开启阻尼
controls.dampingFactor = 0.25;
controls.rotateSpeed = 0.35;
// 设置 '鼠标控制' 是否生效, 默认为生效
// controls.enabled = false;
Questions
- OBJLoader.js和OBJLoader2.js的区别
- 光源拖动
存档
- mesh对象的前三个属性position,rotation和scale有三种设置方法。
- 使用CylinderBufferGeometry创建顶底大小不一致的圆台
资料
- 漫步视角 + 碰撞监测
- 墙体我使用了BoxGeometry,墙体上的窗户的洞、门洞,我们可以使用ThreeBSP库中差集函数来进行模型相减来实现。, ThreeBPS
- BPS使用示例
- 开门动画使用Tween.js
- 计算机图形学中三维数学的一些基础知识,主要包括2D、3D笛卡尔坐标系,向量、矩阵的数学和几何意义以及公式。
- three.js源码注解
碰撞监测思路
- movingCube中心点是否和其他物体重合
- movingCube的中心点是否在其他物体内部
- movingCube的中心点到合个顶点的射线是否和其他物体有交点, 且交点是否小于中心点到定点的距离
let overlap = false;
// collision(collisionArray, object, camera, transformControls);
/**
* 功能:检测 movingCube 是否与数组 collideMeshList 中的元素发生了碰撞
*
*/
const originPoint = movingCube.position.clone();
for (var vertexIndex = 0; vertexIndex < movingCube.geometry.vertices.length; vertexIndex++) {
// 顶点原始坐标
// .clone(); 复制坐标
const localVertex = movingCube.geometry.vertices[vertexIndex].clone();
// 顶点经过变换后的坐标
// .applyMatrix4 ( m : Matrix4 ) 将该向量乘以四阶矩阵m(第四个维度隐式地为1),并按视角划分
const globalVertex = localVertex.applyMatrix4(movingCube.matrix);
// 获得由中心指向顶点的向量,
// .sub ( v : Vector3 ) 从该向量减去向量v。
const directionVector = globalVertex.sub(movingCube.position);
// console.log('中心指向定点的向量', collideMeshList.length);
// v3.push(directionVector);
// 将方向向量初始化
// .normalize () 将该向量转换为单位向量(unit vector), 也就是说,将该向量的方向设置为和原向量相同,但是其长度(length)为1。
const ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
// 检测射线与多个物体的相交情况
const collisionResults = ray.intersectObjects(collideMeshList);
// if (collisionResults.length > 1) {
// console.log('在一条线上', collisionResults);
// }
// 如果返回结果不为空,且交点与射线起点的距离小于物体中心至顶点的距离,则发生了碰撞
if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
// const object = transformControls.object;
// var x, y, x;
// if (!overlap) {
overlap = true;
// const position = object.position;
// x = position.x;
// y = position.y;
// z = position.z;
// } else {
// console.log(x, y, z);
// console.log('重叠');
break;
// object.position.set(x, y, z);
// }
} else {
// console.log('没有重叠');
// overlap = false;
}
}
if (overlap) {
console.log('重叠');
} else {
console.log('不重叠');
const mesh = enti_map.get(name);
const mp = movingCube.position;
mesh.position.set(mp.value, mp.value, mp.value);
}
// const curve = new THREE.CatmullRomCurve3(v3);
// const line = curve.getPoints(50);
// const geometry_line = new THREE.BufferGeometry().setFromPoints(line);
// const material = new THREE.MeshBasicMaterial({
// color: 4500442
// });
// const mesh = new THREE.Line(geometry_line, material);
// scene.add(mesh);
网友评论