您的当前位置:首页正文

Three.js利用顶点绘制立方体的方法详解

2020-11-27 来源:赴品旅游

前言

之前我们在学些WebGL基础的时候每天都是在一直研究顶点位置,法向量,绘制下标什么的。虽然复杂,但是毕竟原生,性能没得说。

three.js也给我们提供了相关的接口供我们使用原生的方法绘制模型,下面话不多说了,来一起看看详细的介绍吧。

下面是我的个人一个案例。

首先,我创建了一个空白的形状:

 //立方体
 var cubeGeometry = new THREE.Geometry();

立方体的形状如下:

 // 创建一个立方体
 // v6----- v5
 // /| /|
 // v1------v0|
 // | | | |
 // | |v7---|-|v4
 // |/ |/
 // v2------v3

然后添加了立方体的顶点,一共8个

 //创建立方体的顶点
 var vertices = [
 new THREE.Vector3(10, 10, 10), //v0
 new THREE.Vector3(-10, 10, 10), //v1
 new THREE.Vector3(-10, -10, 10), //v2
 new THREE.Vector3(10, -10, 10), //v3
 new THREE.Vector3(10, -10, -10), //v4
 new THREE.Vector3(10, 10, -10), //v5
 new THREE.Vector3(-10, 10, -10), //v6
 new THREE.Vector3(-10, -10, -10) //v7
 ];

 cubeGeometry.vertices = vertices;

接着通过顶点的坐标生成了立方体的面

 //创建立方的面
 var faces=[
 new THREE.Face3(0,1,2),
 new THREE.Face3(0,2,3),
 new THREE.Face3(0,3,4),
 new THREE.Face3(0,4,5),
 new THREE.Face3(1,6,7),
 new THREE.Face3(1,7,2),
 new THREE.Face3(6,5,4),
 new THREE.Face3(6,4,7),
 new THREE.Face3(5,6,1),
 new THREE.Face3(5,1,0),
 new THREE.Face3(3,2,7),
 new THREE.Face3(3,7,4)
 ];

 cubeGeometry.faces = faces;

在这里需要注意:

(1)面是由三个顶点组成的一个三角形面,也是WebGL的实现面的方式。如果需要一个长方形,那就需要由两个三角形组合而成。

(2)如果要绘制的面是朝向相机的,那这个面的顶点的书写方式是逆时针绘制的,比如图上模型的第一个面的添加里面书写的是(0,1,2)。

(3)如果能使模型有灯光的效果,还需要设置法向量,让three.js自动生成即可,如下

 //生成法向量
 cubeGeometry.computeFaceNormals();

当前的这些步骤只是生成了形状,还需要和以前一样设置一个纹理,再通过THTEE.Mesh()方法生成网格

 var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x00ffff});

 cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

这样就实现了一个立方体的绘制:

全部代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
 <style type="text/css">
 html, body {
 margin: 0;
 height: 100%;
 }

 canvas {
 display: block;
 }

 </style>
</head>
<body onload="draw();">

</body>
<script src="build/three.js"></script>
<script src="examples/js/controls/OrbitControls.js"></script>
<script src="examples/js/libs/stats.min.js"></script>
<script src="examples/js/libs/dat.gui.min.js"></script>
<script>
 var renderer;
 function initRender() {
 renderer = new THREE.WebGLRenderer({antialias: true});
 renderer.setSize(window.innerWidth, window.innerHeight);
 //告诉渲染器需要阴影效果
 renderer.shadowMap.enabled = true;
 renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 默认的是,没有设置的这个清晰 THREE.PCFShadowMap
 document.body.appendChild(renderer.domElement);
 }

 var camera;
 function initCamera() {
 camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
 camera.position.set(0, 40, 100);
 camera.lookAt(new THREE.Vector3(0, 0, 0));
 }

 var scene;
 function initScene() {
 scene = new THREE.Scene();
 }

 //初始化dat.GUI简化试验流程
 var gui;
 function initGui() {
 //声明一个保存需求修改的相关数据的对象
 gui = {
 lightY: 30, //灯光y轴的位置
 cubeX: 25, //立方体的x轴位置
 cubeY: 10, //立方体的x轴位置
 cubeZ: -5 //立方体的z轴的位置
 };
 var datGui = new dat.GUI();
 //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)
 datGui.add(gui, "lightY", 0, 100);
 datGui.add(gui, "cubeX", -30, 30);
 datGui.add(gui, "cubeY", -30, 30);
 datGui.add(gui, "cubeZ", -30, 30);
 }

 var light;
 function initLight() {
 scene.add(new THREE.AmbientLight(0x444444));

 light = new THREE.PointLight(0xffffff);
 light.position.set(15, 30, 10);

 //告诉平行光需要开启阴影投射
 light.castShadow = true;

 scene.add(light);
 }

 var cube;
 function initModel() {

 //辅助工具
 var helper = new THREE.AxisHelper(10);
 scene.add(helper);

 // 创建一个立方体
 // v6----- v5
 // /| /|
 // v1------v0|
 // | | | |
 // | |v7---|-|v4
 // |/ |/
 // v2------v3

 //立方体
 var cubeGeometry = new THREE.Geometry();

 //创建立方体的顶点
 var vertices = [
 new THREE.Vector3(10, 10, 10), //v0
 new THREE.Vector3(-10, 10, 10), //v1
 new THREE.Vector3(-10, -10, 10), //v2
 new THREE.Vector3(10, -10, 10), //v3
 new THREE.Vector3(10, -10, -10), //v4
 new THREE.Vector3(10, 10, -10), //v5
 new THREE.Vector3(-10, 10, -10), //v6
 new THREE.Vector3(-10, -10, -10) //v7
 ];

 cubeGeometry.vertices = vertices;

 //创建立方的面
 var faces=[
 new THREE.Face3(0,1,2),
 new THREE.Face3(0,2,3),
 new THREE.Face3(0,3,4),
 new THREE.Face3(0,4,5),
 new THREE.Face3(1,6,7),
 new THREE.Face3(1,7,2),
 new THREE.Face3(6,5,4),
 new THREE.Face3(6,4,7),
 new THREE.Face3(5,6,1),
 new THREE.Face3(5,1,0),
 new THREE.Face3(3,2,7),
 new THREE.Face3(3,7,4)
 ];

 cubeGeometry.faces = faces;

 //生成法向量
 cubeGeometry.computeFaceNormals();

 var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x00ffff});

 cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
 cube.position.x = 25;
 cube.position.y = 5;
 cube.position.z = -5;

 //告诉立方体需要投射阴影
 cube.castShadow = true;

 scene.add(cube);

 //底部平面
 var planeGeometry = new THREE.PlaneGeometry(100, 100);
 var planeMaterial = new THREE.MeshLambertMaterial({color: 0xaaaaaa});

 var plane = new THREE.Mesh(planeGeometry, planeMaterial);
 plane.rotation.x = -0.5 * Math.PI;
 plane.position.y = -0;

 //告诉底部平面需要接收阴影
 plane.receiveShadow = true;

 scene.add(plane);

 }

 //初始化性能插件
 var stats;
 function initStats() {
 stats = new Stats();
 document.body.appendChild(stats.dom);
 }

 //用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放
 var controls;
 function initControls() {

 controls = new THREE.OrbitControls(camera, renderer.domElement);

 // 如果使用animate方法时,将此函数删除
 //controls.addEventListener( 'change', render );
 // 使动画循环使用时阻尼或自转 意思是否有惯性
 controls.enableDamping = true;
 //动态阻尼系数 就是鼠标拖拽旋转灵敏度
 //controls.dampingFactor = 0.25;
 //是否可以缩放
 controls.enableZoom = true;
 //是否自动旋转
 controls.autoRotate = false;
 //设置相机距离原点的最远距离
 controls.minDistance = 50;
 //设置相机距离原点的最远距离
 controls.maxDistance = 200;
 //是否开启右键拖拽
 controls.enablePan = true;
 }

 function render() {
 renderer.render(scene, camera);
 }

 //窗口变动触发的函数
 function onWindowResize() {

 camera.aspect = window.innerWidth / window.innerHeight;
 camera.updateProjectionMatrix();
 render();
 renderer.setSize(window.innerWidth, window.innerHeight);

 }

 function animate() {
 //更新控制器
 render();

 //更新性能插件
 stats.update();

 //更新相关位置
 light.position.y = gui.lightY;
 cube.position.x = gui.cubeX;
 cube.position.y = gui.cubeY;
 cube.position.z = gui.cubeZ;

 controls.update();

 requestAnimationFrame(animate);
 }

 function draw() {
 initGui();
 initRender();
 initScene();
 initCamera();
 initLight();
 initModel();
 initControls();
 initStats();

 animate();
 window.onresize = onWindowResize;
 }
</script>
</html>

总结

显示全文