童年原是一生最美妙的阶段,那时的孩子是一朵花,也是一颗果子,是一片懵懵懂懂的聪明,一种永远不息的活动,一股强烈的欲望。——巴尔扎克
现在位置:首页 > 网站建设
  • 内蒙古自治区地方标准《办公用房信息采集规范》正式发布

    转载2022-4-260评论794
    近日,由内蒙古自治区机关事务管理局负责起草的地方标准《办公用房信息采集规范》,经自治区市场监督管理局审查通过并批准发布。 办公用房信息采集是办公用房信息化管理系统业务流程中的重要环节,是实现办公用房数字化管理、开展信息化建设的基础性工作,是各级党政机关办公用房使用状况评定的重要依据。《办公用房信息采集规范》的发布使用,为我区办公用房信息采集工作提供了标准规范、统一参照的科学依据,对提高内蒙古自治区党政机关办公用房管理信息化建设水平,加强自治区各级机关事务管理部门对办公用房的规范管理,保障各级党政机关高效运行,建设节约型机关,起到了积极促进作用。 点击下载: DB15_T 2534-2022 办公用房信息采集规范.pdf
  • 为什么要前后端分离?有什么优缺点?

    一、前戏 前后端分离已成为互联网项目开发的业界标准使用方式,通过nginx+tomcat的方式(也可以中间加一个nodejs)有效的进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如:浏览器,车载终端,安卓,IOS等等)打下坚实的基础。这个步骤是系统架构从猿进化成人的必经之路。 核心思想是前端html页面通过ajax调用后端的restuful api接口并使用json数据进行交互。 在互联网架构中,名词解释: Web服务器:一般指像nginx,apache这类的服务器,他们一般只能解析静态资源。 应用服务器:一般指像tomcat,jetty,resin这类的服务器可以解析动态资源也可以解析静态资源,但解析静态资源的能力没有web服务器好。 一般都是只有web服务器才能被外网访问,应用服务器只能内网访问。 二、术业有专攻(开发人员分离) 以前的JavaWeb项目大多数都是java程序员又当爹又当妈,又搞前端,又搞后端。 随着时代的发展,渐渐的许多大中小公司开始把前后端的界限分的越来越明确,前端工程师只管前端的事情,后端工程师只管后端的事情。正所谓术业有专攻,一个人如果什么都会,那么他毕竟什么都不精。 大中型公司需要专业人才,小公司需要全才,但是对于个人职业发展来说,我建议是分开。 1、对于后端java工程师: 把精力放在java基础,设计模式,jvm原理,spring+springmvc原理及源码,linux,mysql事务隔离与锁机制,mongodb,http/tcp,多线程,分布式架构,弹性计算架构,微服务架构,java性能优化,以及相关的项目管理等等。 后端追求的是:三高(高并发,高可用,高性能),安全,存储,业务等等。 2、对于前端工程师: 把精力放在html5,css3,jquery,angularjs,bootstrap,reactjs,vuejs,webpack,less/sass,gulp,nodejs,Google V8引擎,javascript多线程,模块化,面向切面编程,设计模式,浏览器兼容性,性能优化等等。 前端追求的是:页面表现,速度流畅,兼容性,用户体验等等。 术业有专攻,这样你的核心竞争力才会越来越高,正所谓你往生活中投入什么,生活就会反馈给你什么。并且两端的发展都越来越高深,你想什么都会,那你毕竟什么都不精。 通过将team分成前后端team,让两边的工程师更加专注各自的领域,独立治理,然后构建出一个全栈式的精益求精的team。 三、原始人时代(各种耦合) 几曾何时,我们的JavaWeb项目都是使用了若干后台框架,springmvc/struts + spring + spring jdbc/hibernate/mybatis 等等。 大多数项目在java后端都是分了三层,控制层,业务层,持久层。控制层负责接收参数,调用相关业务层,封装数据,以及路由&渲染到jsp页面。然后jsp页面上使用各种标签或者手写java表达式将后台的数据展现出来,玩的是MVC那套思路。 我们先看这种情况:需求定完了,代码写完了,测试测完了,然后呢?要发布了吧?你需要用maven或者eclipse等工具把你的代码打成一个war包,然后把这个war包发布到你的生产环境下的web容器里,对吧? 发布完了之后,你要启动你的web容器,开始提供服务,这时候你通过配置域名,dns等等相关,你的网站就可以访问了(假设你是个网站)。那我们来看,你的前后端代码是不是全都在那个war包里?包括你的js,css,图片,各种第三方的库,对吧? 浏览器在通过域名通过dns服务器找到你的服务器外网ip,将http请求发送到你的服务器,在tcp3次握手之后(http下面是tcp/ip),通过tcp协议开始传输数据,你的服务器得到请求后,开始提供服务,接收参数,之后返回你的应答给浏览器,浏览器再通过content-type来解析你返回的内容,呈现给用户。 那么我们来看,我们先假设你的首页中有100张图片,此时,用户的看似一次http请求,其实并不是一次,用户在第一次访问的时候,浏览器中不会有缓存,你的100张图片,浏览器要连着请求100次http请求(有人会跟我说http长连短连的问题,不在这里讨论),你的服务器接收这些请求,都需要耗费内存去创建socket来玩tcp传输(消耗你服务器上的计四、JSP的痛点 以前的javaWeb项目大多数使用jsp作为页面层展示数据给用户,因为流量不高,因此也没有那么苛刻的性能要求,但现在是大数据时代,对于互联网项目的性能要求是越来越高,因此原始的前后端耦合在一起的架构模式已经逐渐不能满足我们,因此我们需要需找一种解耦的方式,来大幅度提升我们的负载能力。 1、动态资源和静态资源全部耦合在一起,服务器压力大,因为服务器会收到各种http请求,例如css的http请求,js的,图片的等等。一旦服务器出现状况,前后台一起玩完,用户体验极差。 2、UI出好设计图后,前端工程师只负责将设计图切成html,需要由java工程师来将html套成jsp页面,出错率较高(因为页面中经常会出现大量的js代码),修改问题时需要双方协同开发,效率低下。 3、jsp必须要在支持java的web服务器里运行(例如tomcat,jetty,resin等),无法使用nginx等(nginx据说单实例http并发高达5w,这个优势要用上),性能提不上来。 4、第一次请求jsp,必须要在web服务器中编译成servlet,第一次运行会较慢。 5、每次请求jsp都是访问servlet再用输出流输出的html页面,效率没有直接使用html高(是每次哟,亲~)。 6、jsp内有较多标签和表达式,前端工程师在修改页面时会捉襟见肘,遇到很多痛点。 7、如果jsp中的内容很多,页面响应会很慢,因为是同步加载。 8、需要前端工程师使用java的ide(例如eclipse),以及需要配置各种后端的开发环境,你们有考虑过前端工程师的感受吗。 基于上述的一些痛点,我们应该把整个项目的开发权重往前移,实现前后端真正的解耦! 五、开发模式 以前老的方式是: 1、产品经历/领导/客户提出需求 2、UI做出设计图 3、前端工程师做html页面 4、后端工程师将html页面套成jsp页面(前后端强依赖,后端必须要等前端的html做好才能套jsp。如果html发生变更,就更痛了,开发效率低) 5、集成出现问题 6、前端返工 7、后端返工 8、二次集成 9、集成成功 10、交付 新的方式是: 1、产品经历/领导/客户提出需求 2、UI做出设计图 3、前后端约定接口&数据&参数 4、前后端并行开发(无强依赖,可前后端并行开发,如果需求变求变更,只要接口&参数不变,就不用两边都修改代码,开发效率高) 5、前后端集成 6、前端页面调整 7、集成成功 8、交付 六、请求方式 以前老的方式是: 1、客户端请求 2、服务端的servlet或controller接收请求(后端控制路由与渲染页面,整个项目开发的权重大部分在后端) 3、调用service,dao代码完成业务逻辑 4、返回jsp 5、jsp展现一些动态的代码 新的方式是: 1、浏览器发送请求 2、直接到达html页面(前端控制路由与渲染页面,整个项目开发的权重前移) 3、html页面负责调用服务端接口产生数据(通过ajax等等,后台返回json格式数据,json数据格式因为简洁高效而取代xml) 4、填充html,展现动态效果,在页面上进行解析并操作DOM。 总结一下新的方式的请求步骤: 大量并发浏览器请求--->web服务器集群(nginx)--->应用服务器集群(tomcat)--->文件/数据库/缓存/消息队列服务器集群 同时又可以玩分模块,还可以按业务拆成一个个的小集群,为后面的架构升级做准备。 七、前后分离的优势 1、可以实现真正的前后端解耦,前端服务器使用nginx。前端/WEB服务器放的是css,js,图片等等一系列静态资源(甚至你还可以css,js,图片等资源放到特定的文件服务器,例如阿里云的oss,并使用cdn加速),前端服务器负责控制页面引用&跳转&路由,前端页面异步调用后端的接口,后端/应用服务器使用tomcat(把tomcat想象成一个数据提供者),加快整体响应速度。(这里需要使用一些前端工程化的框架比如nodejs,react,router,react,redux,webpack) 2、发现bug,可以快速定位是谁的问题,不会出现互相踢皮球的现象。页面逻辑,跳转错误,浏览器兼容性问题,脚本错误,页面样式等问题,全部由前端工程师来负责。接口数据出错,数据没有提交成功,应答超时等问题,全部由后端工程师来解决。双方互不干扰,前端与后端是相亲相爱的一家人。 3、在大并发情况下,我可以同时水平扩展前后端服务器,比如淘宝的一个首页就需要2000+台前端服务器做集群来抗住日均多少亿+的日均pv。(去参加阿里的技术峰会,听他们说他们的web容器都是自己写的,就算他单实例抗10万http并发,2000台是2亿http并发,并且他们还可以根据预知洪峰来无限拓展,很恐怖,就一个首页。。。) 4、减少后端服务器的并发/负载压力。除了接口以外的其他所有http请求全部转移到前端nginx上,接口的请求调用tomcat,参考nginx反向代理tomcat。且除了第一次页面请求外,浏览器会大量调用本地缓存。 5、即使后端服务暂时超时或者宕机了,前端页面也会正常访问,只不过数据刷不出来而已。 6、也许你也需要有微信相关的轻应用,那样你的接口完全可以共用,如果也有app相关的服务,那么只要通过一些代码重构,也可以大量复用接口,提升效率。(多端应用) 7、页面显示的东西再多也不怕,因为是异步加载。 8、nginx支持页面热部署,不用重启服务器,前端升级更无缝。 9、增加代码的维护性&易读性(前后端耦在一起的代码读起来相当费劲)。 10、提升开发效率,因为可以前后端并行开发,而不是像以前的强依赖。 11、在nginx中部署证书,外网使用https访问,并且只开放443和80端口,其他端口一律关闭(防止黑客端口扫描),内网使用http,性能和安全都有保障。 12、前端大量的组件代码得以复用,组件化,提升开发效率,抽出来! 八、注意事项 1、在开需求会议的时候,前后端工程师必须全部参加,并且需要制定好接口文档,后端工程师要写好测试用例(2个维度),不要让前端工程师充当你的专职测试,推荐使用chrome的插件postman或soapui或jmeter,service层的测试用例拿junit写。ps:前端也可以玩单元测试吗? 2、上述的接口并不是java里的interface,说白了调用接口就是调用你controler里的方法。 3、加重了前端团队的工作量,减轻了后端团队的工作量,提高了性能和可扩展性。 4、我们需要一些前端的框架来解决类似于页面嵌套,分页,页面跳转控制等功能。(上面提到的那些前端框架)。 5、如果你的项目很小,或者是一个单纯的内网项目,那你大可放心,不用任何架构而言,但是如果你的项目是外网项目,呵呵哒。 6、 以前还有人在使用类似于velocity/freemarker等模板框架来生成静态页面,仁者见仁智者见智。 7、这篇文章主要的目的是说jsp在大型外网java web项目中被淘汰掉,可没说jsp可以完全不学,对于一些学生朋友来说,jsp/servlet等相关的java web基础还是要掌握牢的,不然你以为springmvc这种框架是基于什么来写的? 8、如果页面上有一些权限等等相关的校验,那么这些相关的数据也可以通过ajax从接口里拿。 9、对于既可以前端做也可以后端做的逻辑,我建议是放到前端,为什么?因为你的逻辑需要计算资源进行计算,如果放到后端去run逻辑,则会消耗带宽&内存&cpu等等计算资源,你要记住一点就是服务端的计算资源是有限的,而如果放到前端,使用的是客户端的计算资源,这样你的服务端负载就会下降(高并发场景)。类似于数据校验这种,前后端都需要做! 10、前端需要有机制应对后端请求超时以及后端服务宕机的情况,友好的展示给用户。 九、扩展阅读 1、其实对于js,css,图片这类的静态资源可以考虑放到类似于阿里云的oss这类文件服务器上(如果是普通的服务器&操作系统,存储在到达pb级的文件后,或者单个文件夹内的文件数量达到3-5万,io会有很严重的性能问题),再在oss上配cdn(全国子节点加速),这样你页面打开的速度像飞一样, 无论你在全国的哪个地方,并且你的nginx的负载会进一步降低。 2、如果你要玩轻量级微服务架构,要使用nodejs做网关,用nodejs的好处还有利于seo优化,因为nginx只是向浏览器返回页面静态资源,而国内的搜索引擎爬虫只会抓取静态数据,不会解析页面中的js,这使得应用得不到良好的搜索引擎支持。同时因为nginx不会进行页面的组装渲染,需要把静态页面返回到浏览器,然后完成渲染工作,这加重了浏览器的渲染负担。浏览器发起的请求经过nginx进行分发,URL请求统一分发到nodejs,在nodejs中进行页面组装渲染;API请求则直接发送到后端服务器,完成响应。 3、如果遇到跨域问题,spring4的CORS可以完美解决,但一般使用nginx反向代理都不会有跨域问题,除非你把前端服务和后端服务分成两个域名。JSONP的方式也被淘汰掉了。 4、如果想玩多端应用,注意要去掉tomcat原生的session机制,要使用token机制,使用缓存(因为是分布式系统),做单点,对于token机制的安全性问题,可以搜一下jwt。 5、前端项目中可以加入mock测试(构造虚拟测试对象来模拟后端,可以独立开发和测试),后端需要有详细的测试用例,保证服务的可用性与稳定性。 十、总结 前后端分离并非仅仅只是一种开发模式,而是一种架构模式(前后端分离架构)。千万不要以为只有在撸代码的时候把前端和后端分开就是前后端分离了,需要区分前后端项目。前端项目与后端项目是两个项目,放在两个不同的服务器,需要独立部署,两个不同的工程,两个不同的代码库,不同的开发人员。 前后端工程师需要约定交互接口,实现并行开发,开发结束后需要进行独立部署,前端通过ajax来调用http请求调用后端的restful api。前端只需要关注页面的样式与动态数据的解析&渲染,而后端专注于具体业务逻辑。
  • NFS服务防火墙放行端口

    转载2021-8-250评论2203
    配置NFS服务 虚拟机CentOS系统版本信息: [root@nfs-client ~]# cat /etc/redhat-release  CentOS Linux release 7.4.1708 (Core)  [root@nfs-client ~]#  [root@nfs-client ~]# uname -r 3.10.0-693.el7.x86_64 [root@nfs-client ~]#  [root@nfs-client ~]# uname -m x86_64 [root@nfs-client ~]# uname -n 客户端使用showmount -e 服务器ip 查看共享目录 出现报错: clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host) 原因:服务器端防火墙没有开启nfs服务对应的端口 方法1:实验环境,关闭防火墙 方法2:开启NFS端口 1)服务器开启111和2049端口,111为rpcbind对应端口,2049为nfsd对应端口 firewall-cmd --permanent --add-port=2049/tcp firewall-cmd --permanent --add-port=2049/udp firewall-cmd --permanent --add-port=111/tcp firewall-cmd --permanent --add-port=111/udp firewall-cmd --reload 2)编辑/etc/sysconfig/nfs 修改默认端口,在末尾添加以下内容: RQUOTAD_PORT=30001 LOCKD_TCPPORT=30002 LOCKD_UDPPORT=30002 MOUNTD_PORT=30003 STATD_PORT=30004 3)开启添加的端口 firewall-cmd --permanent --add-port=30001/tcp firewall-cmd --permanent --add-port=30001/udp firewall-cmd --permanent --add-port=30002/tcp firewall-cmd --permanent --add-port=30002/udp firewall-cmd --permanent --add-port=30003/udp firewall-cmd --permanent --add-port=30003/tcp firewall-cmd --permanent --add-port=30004/tcp firewall-cmd --permanent --add-port=30004/udp firewall-cmd --reload 4)重启服务 systemctl restart nfs 5)客户端查看服务器共享目录 [root@nfs-client ~]# showmount -e 192.168.172.190 Export list for 192.168.172.190: /data 192.168.172.0/24
  • 使用ThreeJs搭建BIM模型浏览器-第十步 加载优化

    转载2020-10-160评论7727
    最近在尝试了新的传输方式。不过对QModel而言,影响不是很大,因为QModel这个产品只有首次加载是需要从服务器下载模型数据的。   首先,把原本的模型文件拆分成多份了。原本只有一个zip数据压缩包,现在改为在服务端拆解为N份,根据构件数量每500个压缩为一个包,同时把数据转换为utf8array.然后生成一个索引文件A。 前端首先请求索引文件A。得到数据包的数量,然后进入本文重点。 主线程根据解析索引文件,知道了一共有N个数据包,然后开始启用worker下载。如下 主线程代码: var worker = new Worker("worker.js"); worker.postMessage({m: 模型N}); //向worker发送数据 worker.onmessage = function(evt) { //接收worker传过来的数据函数 var resulti = JSON.parse(evt.data); //开始解析resulti }   然后创建一个worker.js,多线程进行传输并解压。 onmessage = function(evt) { JSZipUtils.getBinaryContent( "数据包N.zip", { callback: function(err, data) { var zipdata = new JSZip(data); var filei = zipdata.file("数据包N.json"); postMessage(filei.asText()); } }); } 实际效果如下图  总结: 1、由于个人服务器原因,带宽就那么大,一个线程跑满和10个线程同时下载,完全没有效率的差异。所以下载起来是一样的。需要硬件支持才体现出传输的优化。 2、数据解析放到线程里面,确实会提升一些效率。 3、下一步优化,可以考虑在worker里面直接把数据转换成Utf8Array或者ArrayBuffer,PostMessage是可以移交这一类对象的控制权的。 原文https://blog.csdn.net/ztz87
  • 使用ThreeJs搭建BIM模型浏览器,第九步-性能优化(2)

    转载2020-10-160评论8328
    感谢网友给的建议。 我之前一直是使用threejs的102dev版本,以为geometry共享了就行了,但是这并不是threejs里面所说的Instance。在新的threejs版本中,新增加了几个很有意思的Instance类,这里重点挑InstancedMesh来说。InstancedMesh与使用一个geometry共享创建出Mesh是不一样的,InstancedMesh最终达到的效果是一次Drawcall,而共享geometry创建出来的Mesh并无此效果,效率跟不共享创建Mesh渲染性能上没有太大区别,只是可能会省点内存。 InstancedMesh是R110之后出现 官网简介: A special version of Mesh with instanced rendering support. Use InstancedMesh if you have to render a large number of objects with the same geometry and material but with different world transformations. The usage of InstancedMesh will help you to reduce the number of draw calls and thus improve the overall rendering performance in your application. 大量相同的几何,会减少绘图调用的次数,大量提高页面性能; 参考文档: http://www.qmodel.cn/threejs/three/docs/index.html#api/en/objects/InstancedMesh 查看示例: http://www.qmodel.cn/threejs/three/examples/?q=instanc#webgl_instancing_raycast 用法: var geometry = new THREE.SphereBufferGeometry( 0.2 ); var material = new THREE.MeshPhongMaterial( { flatShading: true } ); var amount=80 var count=amount*amount*amount; var mesh = new THREE.InstancedMesh( geometry, material, count ); var i = 0; var offset = ( amount - 1 ) / 2; var transform = new THREE.Object3D(); for ( var x = 0; x < amount; x ++ ) { for ( var y = 0; y < amount; y ++ ) { for ( var z = 0; z < amount; z ++ ) { transform.position.set( offset - x, offset - y, offset - z ); transform.updateMatrix(); mesh.setMatrixAt( i ++, transform.matrix ); } } } scene.add( mesh ); 点击获取InstancedId,官方示例 // move function onMouseMove( event ) { event.preventDefault(); mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; } // render function render() { raycaster.setFromCamera( mouse, camera ); var intersection = raycaster.intersectObject( mesh ); if ( intersection.length > 0 ) { // 获取当前实例的ID 索引 var instanceId = intersection[ 0 ].instanceId; // 根据当前的索引 获取当前的矩阵 mesh.getMatrixAt( instanceId, instanceMatrix ); // 更新矩阵 matrix.multiplyMatrices( instanceMatrix, rotationMatrix ); // 设置拾取当前几何的矩阵 mesh.setMatrixAt( instanceId, matrix ); // 更新矩阵 mesh.instanceMatrix.needsUpdate = true; } renderer.render( scene, camera ); } 实际测试性能效率,当使用InstancedMesh时,如上述代码。如果使用的是Mesh,我的渣渣电脑已经渲染不出来了。   如何解决使用InstancedMesh后,构件选择的问题?通过射线相交,可以取到Instance实例的索引ID,可使用ID来找到对应的构件。大家多看官方示例代码就可以了。 补充一点思路,如果网友有更好的方案也欢迎留言。 隐藏构件,把矩阵设置为0矩阵隐藏某个instanceId,0矩阵为[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,] 选择构件:可以考虑把InstancedMesh的geometry和被Pick到的Matrix构造一个新的InstancedMesh放在对应的位置,材质替换为高亮选中的材质,且把原来的Matrix设置为0矩阵,则实现隐藏。实际上目前120版本,Mesh和InstancedMesh还是有不少BUG的,建议全部使用InstancedMesh。 透明度和颜色设置:与选择构件同理,不过考虑到还原操作,对数据的管理会更复杂一些。这里会特征一些内存,效率上也有所降低,最终效果如何,全看编码人员的控制力了。   Merge之后也可以实现Drawcall的减少,且可以实现不同材质的合并。我就尝试过把一整个建筑模型合并成一个geometry,没错,性能提升巨大,且内存锐减一半!merge可以实现不同材质的几何直接合并,但是因为group的处理,还是会拆分为多次drawcall,没有太多作用。关于merge的总结可以看一下后面的介绍。 对比geometry.merge和Instance实例化、普通Mesh。以一个5万构件的全专业(建筑、结构、给排水、暖通、电气)的住宅塔楼为例(复用率还比较高的)。   Instance实例化几何体 Merge合并几何体 普通Mesh Material 相同 相同 可不同 Geometry 相同 可不同 可不同 单个控制 使用索引可实现 难以实现 容易实际 生成时间 快速 Merge需要计算消耗 一般。量大 渲染性能 较优 更优,极致减少drawcall 差 内存占用 极少 较少 较多 Drawcall次数 约1万次 1次 5万次 2020-9-11  关于merge又有了新的发现。 我们来试一下常规情况,直接使用mesh加入12万个构件。渲染有多么困难,降到fps=6 无视材质的merge,看一下对比,geometry合并到8个里面,有所提升,fps=18,drawcall一次没少。 1、为什么drawcall一次没少呢?因为group没有把同材质的合并起来。由些判断drawcall跟group有关。 2、但是为什么性能会有提升?因为视锥剔除不需要计算了啊! 再进一步,把材质全都合并起来,一个geometry就一个material,会达到什么效果呢?看下图。怎么样?fps109,是不是起飞了?当然,它的不易之处在于,首先要按材质先分组,不同material的也就别合并了,技术上可行,但是合并没好处。
  • 使用ThreeJs搭建BIM模型浏览器,第九步-内存优化(1)

    转载2020-10-160评论7325
    添加到场景的mesh,是通过geometry+materail生成的。如果场景内大量重复的构件,或者大量的构件的材质都是相同的,threejs提供这种方案节省内存:共享geometry 和materail。举例说明: 创建300个一样的圆,一般情况可能会写成下面这样 for (let i = 0; i < 300; i++) { let geometry = new THREE.BoxGeometry(10, 10, 10); let material = new THREE.MeshLambertMaterial({color: 0x00ffff}); let mesh = new THREE.Mesh(geometry, material); mesh.position.set(THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200)); group.add(mesh); } 优化的方法是这样写: let geometry = new THREE.BoxGeometry(10, 10, 10); let material = new THREE.MeshLambertMaterial({color: 0x00ffff}); for (let i = 0; i < 300; i++) { let mesh = new THREE.Mesh(geometry, material); mesh.position.set(THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200)); group.add(mesh); } 注意了,大佬的博客都点到为止,不会告诉你这样的弊端,你一试就知道在BIM浏览器这样做会存在的问题! 因为所有的构件都共享了materail,你怎么实现点击选中,点击选中之后给构件赋予颜色,结果所有同类构件都被渲染成相同的颜色!因为materail是共享的,对materail改个颜色会感觉被选中了一大片。 解决思路很简单,简单到我都没代码可分享:针对选中的构件(或者要赋予颜色的构件),临时替换一个materail即可(曲线救国)! 以前每个构件的纹理材质单独创建时,可以直接赋予颜色,如下图: 现在赋予颜色可以新建一个material给它。当然material新建之后也要管理好,以免内存膨胀;旧的材质纹理要缓存起来,用于恢复默认。相当于给构件弄了个新的包装盒,旧的也别丢掉,还要用的。 Revit自带的这个模型叫做Arch Link Model.rvt,它的材质有点多,有42种,即使这样也明显节省了20%的内存。如果是机电专业,管道设备几乎不在意材质,都是通用的材质纹理,一共就不需要创建几个material,估计会有惊喜。 这是第一步内存优化,针对材质纹理的。后面还会针对Revit导出的几何体进行分析,计算相同形状的构件,以实现文件的压缩和前端的提效。
  • 使用ThreeJs搭建BIM模型浏览器,第八步-边缘线

    转载2020-10-160评论7232
    这个辅助线条,一般称为辅助线,类似草图里的草稿线条。下面分别是有线条和没有线条的对比。 在Threejs对面的边缘添加线条,其实很简单。可以从官方示例中找到。 var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 ); var edges = new THREE.EdgesGeometry( geometry ,89);//大于度才添加线条 var line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0xffffff } ) ); scene.add( line );  https://threejs.org/docs/index.html#api/en/geometries/EdgesGeometry 注意:如果以三角面的方式去添加边缘线,往往会出现很多问题,需要依赖正确的法向量,只针对夹角大于等于90度的面添加边缘线效果会好一些,否则线条过多,对性能负担重,效果也很乱。
  • 使用ThreeJs搭建BIM模型浏览器,第七步-测量

    转载2020-10-160评论7501
    前面说到构件选择,实现了点击时与界面记录的焦点。《使用ThreeJs搭建BIM模型浏览器,第二步-构件选择》 主要的实现思路是:通过一个全局标记,记录前一次点击(作为起点)和后一次点击(作为终点),求两点之前的距离。 然后在终点附近插件一个标签。插件标签的方法前面也提到了。如意门:《使用ThreeJs搭建BIM模型浏览器 第三步 浮标》   1,点击,当然要加起点终点的全局变量记录一下。 mouseUp: function(event) { var vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, 0.5); vector = vector.unproject(this.camera); var raycaster = new THREE.Raycaster(this.camera.position, vector.sub(this.camera.position).normalize()); var intersects = raycaster.intersectObjects(this.scene.children); console.log(intersects[0].point);//这就是焦点。 } 2,在点击始末位置画个小球: function sphere(x, y, z, color, opacity, r) { var sphereGeo = new THREE.SphereGeometry(r, 10, 10); //创建球体 var sphereMat = new THREE.MeshLambertMaterial({ //创建材料 color: color, wireframe: false, transparent: true, side: THREE.DoubleSide, opacity: opacity }); var dwq = new THREE.Mesh(sphereGeo, sphereMat); //创建球体网格模型 dwq.position.set(x, y, z); //设置球的坐标 // this.scene.add(dwq); //将球体添加到场景 //this.mGroup.add(dwq); return dwq; } sphere(point.x, point.y, point.z, 0xFF0000, 1, 0.2) 3,在两点之间画条线: var material = new THREE.LineBasicMaterial({ color: 0x0000ff }); var geometry = new THREE.Geometry(); geometry.vertices.push(this.mp1);  geometry.vertices.push(sel.point); var line = new THREE.Line(geometry, material); // scene.add(line); //mGroup.add(line); //建议用group来放小球和线 4,画个标签,看之前的文章,此处略。 5,看结果 6,优化的目标,可以在MouseOver的时候尝试把点自动的定位到面的边缘,会好用很多!
  • 使用ThreeJs搭建BIM模型浏览器 第六步 纹理贴图(材质)

    转载2020-10-160评论7270
    上效果图 解决思路: Threejs上没啥好说的。看郭老师的博客:http://www.yanhuangxueyuan.com/Three.js_course/texture.html Revit上如何导出呢,不好意思,这次真不能贴核心代码了。。
  • 使用ThreeJs搭建BIM模型浏览器 第五步 漫游

    转载2020-10-160评论7371
    基础的键盘操作漫游其实很好解决。Threejs有一个FlyControl这个控制器,就是完成键盘操作的。 废话不说,上图   关键代码   <script src="js/controls/FlyControls.js"></script> //用FlyControl代替常用的OrbitControls controls =new THREE.FlyControls(this.camera); controls.movementSpeed = 100; //设置移动的速度 controls.rollSpeed = Math.PI / 6; //设置旋转速度 controls.autoForward = false; controls.dragToLook = true;  

sitemap