多数情况下使用组可以很容易地操纵和管理大量网格。但是当对象的数量非常多时,性能就会成为一个瓶颈。使用组,每个对象还是独立的,仍然需要对它们分别进行处理和渲染。通过THREE.Geometry.merge()函数,你可以将多个几何体合并起来创建一个联合体。
当我们使用普通组的情况,绘制20000个立方体,帧率在15帧左右,如果我们选择合并以后,再绘制两万,就会发现,我们可以轻松的渲染20000个立方体,而且没有性能的损失。合并的代码如下:
//合并模型,则使用merge方法合并 var geometry = new THREE.Geometry(); //merge方法将两个几何体对象或者Object3D里面的几何体对象合并,(使用对象的变换)将几何体的顶点,面,UV分别合并. //THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead. for(var i=0; i<gui.numberOfObjects; i++){ var cube = addCube(); cube.updateMatrix(); geometry.merge(cube.geometry, cube.matrix); } scene.add(new THREE.Mesh(geometry, cubeMaterial));THREE.GeometryUtils.merge()已经将此方法移动到了THREE.Geometry对象的上面了,我们使用addCube方法进行立方体的创建,为了确保能正确的定位和旋转合并的THREE.Geometry对象,我们不仅向merge函数提供THREE.Geometry对象,还提供该对象的变换矩阵。当我们将此矩阵添加到merge函数后,那么合并的方块将被正确定位。
假设变量含义如下:
最底层的高度:bottomHight
每排库位组X轴位置:positionX
每排库位组Y轴位置:positionY
每排库位组Z轴位置:positionZ
每排库位组X轴方向数量:binXNum
每排库位组Y轴方向数量:binYNum
每排库位组Z轴方向数量:binZNum
库位长:binLength
库位宽:binWidth
库位高:binHeight
长:可配置的固定数值(rackLengh = 3)
宽:可配置的固定数值 ( rackWidth = 3)
高(rackHeight):bottomHight+(binYNum-1)*binHeight
左侧柱子X: positionX-binLength/2+rackLengh /2
右侧柱子X:positionX+binLength/2-rackLengh /2
柱子Y轴坐标:positionY-binHeight/2
柱子Z轴坐标:positionZ-(this.binZNum * this.binWidth/2)+i * binWidth+rackWidth/2
长:库位的长
宽:库位的宽
高:默认为2
X轴:positionX
Y轴坐标:bottomHight+positionY-binHeight/2-rackHeight/2+ j * this.binHeight
Z轴坐标:positionZ - shelfWidth/2+binWidth/2+i * this.binWidth
下面是我们创建货架的核心代码:
unction StoreShelf(option) { this.binLength = option.BinLength||50;//库位长度 this.binWidth = option.BinWidth||50;//库位宽 this.binHeight = option.BinHeight||50;//库位高 this.binXNum = option.BinXNum||1;//库位X轴方向库位数量 this.binZNum = option.BinZNum||10;//库位Z轴方向库位数量 this.binYNum = option.BinYNum||10;//库位Y轴库位数量 this.bottomHight = option.BottomHeight||20;//底层高度,底层 this.positionX = option.Position.X||0;//库位位置 this.positionY = option.Position.Y||0;//库位位置 this.positionZ = option.Position.Z||0;//库位位置 this.rackLengh = 3;//支架的长度,默认设动为3 this.rackWidth = 3;//支架的宽度,默认设定为3 this.intervalRackNum=2;//间隔多少库位有一个主支架 let binHolderPlane=new THREE.BoxGeometry(this.binLength,2,this.binWidth);//定义一个跟库位长宽相同的几何体,作为托盘 let shlefMat = new THREE.MeshLambertMaterial({color:0x175EC0});//定义支架和托盘的材质 let group = new THREE.Group();//定义一个组合体 //合并模型,则使用merge方法合并 let combineGeometry = new THREE.Geometry(); /* 支架的高=最底层的高度+(库位数-1)*库位的高度 */ let rackHeight=this.bottomHight+(this.binYNum-1)*this.binHeight; /* 支架的宽=库位数乘以库位的宽度 */ let shelfWidth=this.binZNum*this.binWidth; let rackBoxGeometry=new THREE.BoxGeometry(this.rackLengh,rackHeight,this.rackWidth);//定义一个支架网格 let rackObject=new THREE.Mesh( rackBoxGeometry, shlefMat, 0 ); let plane = new THREE.BoxGeometry(this.binLength, 2, this.binWidth); let holderObject = new THREE.Mesh(plane, shlefMat,0); let leftPositionX=this.positionX-this.binLength/2+this.rackLengh/2;//左侧支架柱的X轴条码 let rightPositionX=this.positionX+this.binLength/2-this.rackLengh/2;//右侧支架柱的X轴条码 let positionY=this.positionY-this.binHeight/2;//支架柱的Y轴坐标 for(let i=0;i<this.binZNum+this.intervalRackNum;i++) { let isRack=i%this.intervalRackNum; if(isRack==0) { let PositionZ=this.positionZ-shelfWidth/2+i*this.binWidth+this.rackWidth/2; if(i>=this.binZNum) { PositionZ=PositionZ-this.rackWidth; } let leftRack=rackObject.clone(); leftRack.position.set(leftPositionX,positionY,PositionZ); leftRack.updateMatrix(); combineGeometry.merge(leftRack.geometry, leftRack.matrix); let rightRack=rackObject.clone(); rightRack.position.set(rightPositionX,positionY,PositionZ); rightRack.updateMatrix(); combineGeometry.merge(rightRack.geometry, rightRack.matrix); } } //创建托板 for(let i=0;i<this.binZNum;i++) { for (let j = 0; j < this.binYNum; j++) { let positionY=this.positionY-this.binHeight/2-rackHeight/2+this.bottomHight+j*this.binHeight; let positionZ=this.positionZ-shelfWidth/2+this.binWidth/2 + i * this.binWidth let holderObj= holderObject.clone(); holderObj.position.set(this.positionX,positionY,positionZ); holderObj.updateMatrix(); combineGeometry.merge(holderObj.geometry, holderObj.matrix); } } let shelf= new THREE.Mesh(combineGeometry, shlefMat); shelf.uuid=option.No; shelf.name=option.Name; shelf.type="StoreShelf"; return shelf; }创建完成后我们的效果如下:
如果大家需要更加详细的讲解和全部源代码的话,可以看一下我的网易云课堂。当然剩下的博客我也会把核心代码给大家列出来。 大家可以看看我的网易云课堂
网易云课堂-threejs3D智能工厂应用