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 相关文章推荐
window.open()弹出居中的窗口
Feb 01 Javascript
javascript 多级checkbox选择效果
Aug 20 Javascript
SyntaxHighlighter 3.0.83使用笔记
Jan 26 Javascript
jquery+easeing实现仿flash的载入动画
Mar 10 Javascript
BootStrap树状图显示功能
Nov 24 Javascript
解析ajaxFileUpload 异步上传文件简单使用
Dec 30 Javascript
jQueryeasyui 中如何使用datetimebox 取两个日期间相隔的天数
Jun 13 jQuery
使用Angular自定义字段校验指令的方法示例
Feb 01 Javascript
js array数组对象操作方法汇总
Mar 18 Javascript
vue全局自定义指令-元素拖拽的实现代码
Apr 14 Javascript
mpvue实现左侧导航与右侧内容的联动
Oct 21 Javascript
JavaScript HTML DOM 元素 (节点)新增,编辑,删除操作实例分析
Mar 02 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 流程控制switch的简单实例
2016/06/07 PHP
PHP定时任务获取微信access_token的方法
2016/10/10 PHP
PHP基于双向链表与排序操作实现的会员排名功能示例
2017/12/26 PHP
JQuery扩展插件Validate 1 基本使用方法并打包下载
2011/09/05 Javascript
兼容IE、FireFox、Chrome等浏览器的xml处理函数js代码
2011/11/30 Javascript
jquery如何根据值设置默认的选中项
2014/03/17 Javascript
angularjs基础教程
2014/12/25 Javascript
png在IE6 下无法透明的解决方法汇总
2015/05/21 Javascript
使用AngularJS处理单选框和复选框的简单方法
2015/06/19 Javascript
jQuery简单实现点击文本框复制内容到剪贴板上的方法
2016/08/01 Javascript
javascript汉字拼音互转的简单实例
2016/10/09 Javascript
Bootstrap和Java分页实例第一篇
2016/12/23 Javascript
js正则表达式校验指定字符串的方法
2018/07/23 Javascript
vue+echarts实现可拖动节点的折线图(支持拖动方向和上下限的设置)
2019/04/12 Javascript
jquery 回调操作实例分析【回调成功与回调失败的情况】
2019/09/27 jQuery
vuex实现购物车的增加减少移除
2020/06/28 Javascript
解决vant中 tab栏遇到的坑 van-tabs
2020/11/04 Javascript
Python实现string字符串连接的方法总结【8种方式】
2018/07/06 Python
Django-Rest-Framework 权限管理源码浅析(小结)
2018/11/12 Python
Python通用函数实现数组计算的方法
2019/06/13 Python
python圣诞树编写实例详解
2020/02/13 Python
python 获取域名到期时间的方法步骤
2021/02/10 Python
HTML5新增form控件和表单属性实例代码详解
2019/05/15 HTML / CSS
中国网上药店领导者:1药网
2017/02/16 全球购物
西班牙最大的婴儿用品网上商店:Bebitus
2019/05/30 全球购物
网络工程师个人的自我评价范文
2013/10/01 职场文书
园林毕业生自我鉴定范文
2013/12/29 职场文书
校园报刊亭的创业计划书
2014/01/02 职场文书
离婚协议书怎么写2014
2014/09/30 职场文书
党的群众路线教育实践活动制度建设计划方案
2014/10/31 职场文书
2014年客房服务员工作总结
2014/11/18 职场文书
实习工作表现评语
2014/12/31 职场文书
爱心捐赠活动简讯
2015/07/20 职场文书
2019同学聚会主持词
2019/05/06 职场文书
python 模拟在天空中放风筝的示例代码
2021/04/21 Python
MySQL 8.0 Online DDL快速加列的相关总结
2021/06/02 MySQL