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


Posted in Javascript onSeptember 27, 2017

前言

之前我们在学些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);

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

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

全部代码如下:

<!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>

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用Three.js具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
zeroclipboard复制到剪切板的flash
Aug 04 Javascript
JS在IE下缺少标识符的错误
Jul 23 Javascript
javascript实现图片延迟加载方法汇总(三种方法)
Aug 27 Javascript
Javascript中的Prototype到底是什么
Feb 16 Javascript
jQuery实现下拉加载功能实例代码
Apr 01 Javascript
跨域资源共享 CORS 详解
Apr 26 Javascript
JavaScript中正则表达式判断匹配规则及常用方法
Aug 03 Javascript
JavaScript判断变量名是否存在数组中的实例
Dec 28 Javascript
JavaScript比较同一天的时间大小实例代码
Feb 09 Javascript
详解Vue.js项目API、Router配置拆分实践
Mar 16 Javascript
Vue-router 中hash模式和history模式的区别
Jul 24 Javascript
详解vuex之store源码简单解析
Jun 13 Javascript
js实现扫雷小程序的示例代码
Sep 27 #Javascript
Three.js如何实现雾化效果示例代码
Sep 27 #Javascript
浅谈Angular4中常用管道
Sep 27 #Javascript
深入理解Vue.js源码之事件机制
Sep 27 #Javascript
js截取字符串功能的实现方法
Sep 27 #Javascript
详解node+express+ejs+bootstrap构建项目
Sep 27 #Javascript
Three.js基础学习之场景对象
Sep 27 #Javascript
You might like
php smarty函数扩展
2010/03/15 PHP
Javascript - HTML的request类
2006/07/15 Javascript
javascript 传统事件模型构造的事件监听器实现代码
2010/05/31 Javascript
nodejs中exports与module.exports的区别详细介绍
2013/01/14 NodeJs
JavaScript的Ext JS框架中的GridPanel组件使用指南
2016/05/21 Javascript
Javascript如何判断数据类型和数组类型
2016/06/22 Javascript
AngularJS HTML DOM详解及示例代码
2016/08/17 Javascript
微信小程序 教程之条件渲染
2016/10/18 Javascript
微信小程序 常见问题总结(4058,40013)及解决办法
2017/01/11 Javascript
利用Angular+Angular-Ui实现分页(代码加简单)
2017/03/10 Javascript
利用js定义一个导航条菜单
2017/03/14 Javascript
jQuery事件_动力节点Java学院整理
2017/07/05 jQuery
vue 插值 v-once,v-text, v-html详解
2018/01/19 Javascript
python回调函数的使用方法
2014/01/23 Python
python文件操作之批量修改文件后缀名的方法
2018/08/10 Python
selenium+python实现自动化登录的方法
2018/09/04 Python
python批量下载网站马拉松照片的完整步骤
2018/12/05 Python
详解pandas中iloc, loc和ix的区别和联系
2020/03/09 Python
linux 下selenium chrome使用详解
2020/04/02 Python
基于Keras的格式化输出Loss实现方式
2020/06/17 Python
python 爬虫基本使用——统计杭电oj题目正确率并排序
2020/10/26 Python
Python解析微信dat文件的方法
2020/11/30 Python
html5 touch事件实现触屏页面上下滑动(二)
2016/03/10 HTML / CSS
日本必酷网络直营店:Biccamera
2019/03/23 全球购物
德国受欢迎的旅游和休闲网站:lastminute.de
2019/09/23 全球购物
法国在线药房:1001Pharmacies
2021/03/07 全球购物
C语言如何决定使用那种整数类型
2016/11/26 面试题
四风问题自查报告剖析材料
2014/02/08 职场文书
优秀护士获奖感言
2014/02/20 职场文书
医生学习党的群众路线教育实践活动心得体会
2014/11/03 职场文书
小学教师2014年度工作总结
2014/12/03 职场文书
小学六年级班主任工作经验交流材料
2015/11/02 职场文书
校运会班级霸气口号
2015/12/24 职场文书
家庭教育教师培训学习体会
2016/01/14 职场文书
《工作是最好的修行》读后感3篇
2019/12/13 职场文书
Python捕获、播放和保存摄像头视频并提高视频清晰度和对比度
2022/04/14 Python