three.js 利用uv和ThreeBSP制作一个快递柜功能


Posted in Javascript onAugust 18, 2020

最近有three网友,问我要不要学习blender,其实我感觉学习一下也无妨,不过花大量时间精通,尚可不必,术业有专攻给别人留一条路吧,哈哈。那我我们就是用ThreeBSP和uv贴图的知识来制作一个定制化的快递柜,先上图,在线案例请点击博客原文。

three.js 利用uv和ThreeBSP制作一个快递柜功能

下面我们来讲解一下这样一个柜子的制作。

1. 主角是一个JSON

这样一个快递柜的核心是JSON数据的创建,有了jSON数据,我们就可以通过循环遍历出柜子,柜门和uv映射关系。那面下面来看看我们的JSON数据(部分代码)。

var doorArray = [
  [94, 10, -176, 196, false], [94, 10, -76, 196, false], [94, 10, 76, 196, false], [94, 10, 176, 196, false], [46, 15, 0, 186, false], [46, 60, 0, 147, false],
  [46, 21, 0, 105.5, true], [46, 10, 0, 89, true], [46, 10, 0, 78, true], [46, 20, 0, 62, true], [46, 20, 0, 41, true], [46, 20, 0, 20, true]
]

他是以一个数组的形式表现的,每一个数组代表一个柜子数据,每一个数组中的第一项为当前柜子宽度,第二项为高度,第三项为中心x位置,第四项而中心y位置,第五项为柜子是否能打开(因为有的地方为操作面板等)。

2. ThreeBSP绘制柜子的整体架构。

说完核心,我们在看看柜子的整体框架。下面是柜子的侧面图,通过侧面图我们可以很清晰的看出我们做了什么

three.js 利用uv和ThreeBSP制作一个快递柜功能

其实加的不多,就是在上面加了一个檐,下面加了两个底座,还有就是在每个小快递柜中掏出一个洞。
我们看代码

var texture = new THREE.TextureLoader().load('/static/images/base/cabinet.jpg')
let pubMate = new THREE.MeshNormalMaterial();
let frameGeom = new THREE.BoxGeometry(450, 200, 50);
let frameMesh = new THREE.Mesh(frameGeom, pubMate);
frameMesh.position.y = 106;

let footShape = new THREE.Shape();
footShape.moveTo(0, 2);
footShape.lineTo(8, -2);
footShape.lineTo(8, -4);
footShape.lineTo(0, -4);
footShape.lineTo(0, 0);
footShape.lineTo(-12, 0);
footShape.lineTo(-12, 2);
footShape.lineTo(0, 2);

let footExtrudeSettings = {
  steps: 5,
  depth: 450,
  bevelEnabled: false
};
let footGeom = new THREE.ExtrudeGeometry(footShape, footExtrudeSettings);
let footMesh = new THREE.Mesh(footGeom, pubMate);
let footMesh1 = footMesh.clone();
footMesh1.rotation.y = -Math.PI / 2;
footMesh1.position.x = 225;
footMesh1.position.y = 4;
footMesh1.position.z = 25;
let footMesh2 = footMesh.clone();
footMesh2.rotation.y = Math.PI / 2;
footMesh2.position.x = -225;
footMesh2.position.y = 4;
footMesh2.position.z = -25;

let headGeom = new THREE.BoxGeometry(450, 5, 20);
let headMesh = new THREE.Mesh(headGeom, pubMate);
headMesh.position.z = 23;
headMesh.position.y = 206 - 2.5;

let framebsp = new ThreeBSP(frameMesh);
let foot1bsp = new ThreeBSP(footMesh1);
let foot2bsp = new ThreeBSP(footMesh2);
let headbsp = new ThreeBSP(headMesh);

res = framebsp.union(foot1bsp).union(foot2bsp).union(headbsp);

for(var i=0; i<doorArray.length; i++) {
  let geom = new THREE.BoxGeometry(doorArray[i][0]-1, doorArray[i][1]-1, 50);
  let mesh = new THREE.Mesh(geom, pubMate);
  mesh.position.set(doorArray[i][2], doorArray[i][3], 4)
  let meshbsp = new ThreeBSP(mesh);
  res = res.subtract(meshbsp);
}

let cabinetGeom = res.toGeometry();
let cabinetMate = new THREE.MeshPhongMaterial({color: 0xD8C513, specular: 0xD8C513, shininess: 10});
let cabinetMesh = new THREE.Mesh(cabinetGeom, cabinetMate);
cabinetMesh.position.y = 106;

scene.add(cabinetMesh);

这里就是在框架BoxGeometry的基础上加了两个底座ExtrudeGeometry,和一个檐BoxGeometry,然后遍历减去小柜子。掌握好各自的空间位置,制作其实并不难。

3. 柜子的统一贴图

将一张图作为贴图,贴到所有的mesh上,如最上面图的效果,因为上节课已经大致的说了关于uv的一点知识。

for(var i=0; i<doorArray.length; i++) {
    let a0 = doorArray[i][0];
  let a1 = doorArray[i][1];
  let a2 = doorArray[i][2];
  let a3 = doorArray[i][3];

  let x1 = ((a2 - a0 / 2) + 223) / 446;
  let x2 = ((a2 + a0 / 2) + 223) / 446;
  let y1 = ((a3 - a1 / 2) - 10) / 191;
  let y2 = ((a3 + a1 / 2) - 10) / 191;

  doorMesh.geometry.faceVertexUvs[0][8] = [new THREE.Vector2(x1, y2), new THREE.Vector2(x1, y1), new THREE.Vector2(x2, y2)];
  doorMesh.geometry.faceVertexUvs[0][9] = [new THREE.Vector2(x1, y1), new THREE.Vector2(x2, y1), new THREE.Vector2(x2, y2)];
}

上面已经说过,这里的a0是柜子的宽,a1是柜子的高,a2是柜子中心x的坐标值,a3是柜子中心y的坐标值。因为柜子整体x的范围是[-223, 223],y的范围的[10, 201]。经过换算x1是纹理x坐标的最小值,x2是纹理x坐标的最大值,y1是纹理y坐标的最小值,y2是纹理y坐标的最大值,最后设置数组索引为8和9小三角面的uv映射(因为我们要设置的面为长方体的左面,就是8和9控制的面)。

最后加上一点点开柜子的动画就大功告成了。

转载请注明地址:郭先生的博客

到此这篇关于three.js 利用uv和ThreeBSP制作一个快递柜功能的文章就介绍到这了,更多相关three.js 制作快递柜内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js查找父节点的简单方法
Jun 28 Javascript
初窥JQuery(二)事件机制(2)
Dec 06 Javascript
当鼠标移动到图片上时跟随鼠标显示放大的图片效果
Jun 06 Javascript
js特效,页面下雪的小例子
Jun 17 Javascript
JavaScript实现存储HTML字符串示例
Apr 21 Javascript
jquery模拟进度条实现方法
Aug 03 Javascript
Jquery easyui开启行编辑模式增删改操作
Jan 14 Javascript
41个Web开发者必须收藏的JavaScript实用技巧
Jul 22 Javascript
AngularJS 实现JavaScript 动画效果详解
Sep 08 Javascript
vue.js树形组件之删除双击增加分支实例代码
Feb 28 Javascript
javascript数组拍平方法总结
Jan 20 Javascript
Vue.js 通过jQuery ajax获取数据实现更新后重新渲染页面的方法
Aug 09 jQuery
js+css实现扇形导航效果
Aug 18 #Javascript
js实现3D旋转效果
Aug 18 #Javascript
Vue elementui字体图标显示问题解决方案
Aug 18 #Javascript
详解三种方式在React中解决绑定this的作用域问题并传参
Aug 18 #Javascript
javascript实现移动端上传图片功能
Aug 18 #Javascript
八种Vue组件间通讯方式合集(推荐)
Aug 18 #Javascript
小程序实现上传视频功能
Aug 18 #Javascript
You might like
AM/FM收音机的安装与调试
2021/03/02 无线电
分享PHP header函数使用教程
2013/09/05 PHP
php数组删除元素示例
2014/03/21 PHP
PHP使用xmllint命令处理xml与html的方法
2014/12/15 PHP
php获取文件后缀的9种方法
2016/03/22 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
2016/09/23 PHP
PHP+redis实现的悲观锁机制示例
2018/06/12 PHP
修改或扩展jQuery原生方法的代码实例
2015/01/13 Javascript
js实现仿百度风云榜可重复多次调用的TAB切换选项卡效果
2015/08/31 Javascript
jQuery插件FusionWidgets实现的Bulb图效果示例【附demo源码下载】
2017/03/23 jQuery
JS实现的二叉树算法完整实例
2017/04/06 Javascript
react-native-fs实现文件下载、文本存储的示例代码
2017/09/22 Javascript
jQuery实现表单动态加减、ajax表单提交功能
2018/06/08 jQuery
JavaScript实现动态添加、移除元素或属性的方法分析
2019/01/03 Javascript
uploadify插件实现多个图片上传并预览
2019/09/30 Javascript
微信小程序保持session会话的方法
2020/03/20 Javascript
如何在postman中添加cookie信息步骤解析
2020/06/30 Javascript
使用python编写批量卸载手机中安装的android应用脚本
2014/07/21 Python
Python实现的监测服务器硬盘使用率脚本分享
2014/11/07 Python
socket + select 完成伪并发操作的实例
2017/08/15 Python
对Python 内建函数和保留字详解
2018/10/15 Python
Python中collections模块的基本使用教程
2018/12/07 Python
Python面向对象程序设计OOP深入分析【构造函数,组合类,工具类等】
2019/01/05 Python
PyCharm设置每行最大长度限制的方法
2019/01/16 Python
pymysql 插入数据 转义处理方式
2020/03/02 Python
Pytorch 使用CNN图像分类的实现
2020/06/16 Python
如何在mac下配置python虚拟环境
2020/07/06 Python
python 如何调用远程接口
2020/09/11 Python
大学生先进事迹材料
2014/02/16 职场文书
低碳环保倡议书
2014/04/14 职场文书
优秀共产党员先进事迹材料
2014/05/06 职场文书
学校文明单位申报材料
2014/05/06 职场文书
2014领导班子四风问题查摆思想汇报
2014/09/13 职场文书
关于随地扔垃圾的检讨书
2014/09/30 职场文书
80后婚前协议书范本
2014/10/24 职场文书
董事长秘书工作总结
2015/08/14 职场文书