100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > threejs中bufferGeometry合并几何体实现

threejs中bufferGeometry合并几何体实现

时间:2024-07-25 10:45:36

相关推荐

threejs中bufferGeometry合并几何体实现

效果图

在项目中升级threejs版本,原版本中用到了Geometry.merge()方法。升级后的threejs删除了Geometry相关类,转而使用BufferGeometry实现生成几何体。BufferGeometry中的merge()方法使用后,并未将多个几何体进行合并,故自实现了合并多个几何体的功能。

本文中的合并几何体函数只对position、normal、uv、groups进行了合并,合并的几何体为shape拉伸的多个几何体,且为表面和侧立面分别使用不同的material。

以下为实现合并多个几何体方法代码(方法参照javascript - How to merge two BufferGeometries in one BufferGeometry in Three.JS? - Stack Overflow):

const mergeBufferGeometry = function (objects) {const sumPosArr = new Array();const sumNormArr = new Array();const sumUvArr = new Array();const modelGeometry = new THREE.BufferGeometry();let sumPosCursor = 0;let sumNormCursor = 0;let sumUvCursor = 0;let startGroupCount = 0;let lastGroupCount = 0;for (let a = 0; a < objects.length; a++ ){const posAttArr = objects[a].geometry.getAttribute('position').array;for (let b = 0; b < posAttArr.length; b++){sumPosArr[b + sumPosCursor] = posAttArr[b];}sumPosCursor += posAttArr.length;const numAttArr = objects[a].geometry.getAttribute('normal').array;for (let b = 0; b < numAttArr.length; b++){sumNormArr[b + sumNormCursor] = numAttArr[b];}sumNormCursor += numAttArr.length;const uvAttArr = objects[a].geometry.getAttribute('uv').array;for (let b = 0; b < uvAttArr.length; b++){sumUvArr[b + sumUvCursor] = uvAttArr[b];}sumUvCursor += uvAttArr.length;const groupArr = objects[a].geometry.groups;for (let b = 0; b < groupArr.length; b++){startGroupCount = lastGroupCountmodelGeometry.addGroup(startGroupCount, groupArr[b].count, groupArr[b].materialIndex)lastGroupCount = startGroupCount + groupArr[b].count}}modelGeometry.setAttribute('position', new THREE.Float32BufferAttribute(sumPosArr, 3 ));sumNormArr.length && modelGeometry.setAttribute('normal', new THREE.Float32BufferAttribute(sumNormArr, 3 ));sumUvArr.length && modelGeometry.setAttribute('uv', new THREE.Float32BufferAttribute(sumUvArr, 2 ));return modelGeometry}

1)objects 传参:需要合并的几何体数组,mesh数组

2)position 合并:将 objects 数组中几何体的 position 合并至一个数组中,最后将全部 position 添加至新创建的 modelGeometry 中并返回

3)normal 合并:将 objects 数组中几何体的 normal 合并至一个数组中,最后将全部 normal 添加至新创建的 modelGeometry 中并返回

4)uv 合并:将 objects 数组中几何体的 uv 合并至一个数组中,最后将全部 uv 添加至新创建的 modelGeometry 中并返回

5)groups 合并:单个 groups:{ start: Integer, count: Integer, materialIndex: Integer },合并 groups 需要重新计算 start 的值(注意此处的 count 个数并不是 position 个数),下一个 start 的值总是等于上一个 start + count 。本文中 groups 来源为创建ExtrudeGeometry几何体时,传入了表面和侧立面的 material。

生成地图3D图形代码部分

drawChinaMap() {const chinaGroup = new THREE.Group()const bumpMap = new THREE.TextureLoader().load(require('./assets/img/normal1.jpg'), texture => {texture.wrapS = texture.wrapT = THREE.RepeatWrapping;texture.offset.set( 0, 0.5 )texture.repeat.set( 0.01, 0.01 )})chinaGeometry.features.forEach(chinaItem => {let oneCityLineGroup = new THREE.Group()let oneCityLineArr = []let oneCityShapelet oneCityShapeArr = []let material1 = new THREE.ShaderMaterial({uniforms: Shader1.uniforms,vertexShader: Shader1.vertexShader,fragmentShader: Shader1.fragmentShader,side: THREE.DoubleSide,transparent: true,// blending: THREE.AdditiveBlending,})let material2 = new THREE.MeshStandardMaterial({// color: '#7293b5',bumpMap: bumpMap,// map: bumpMap,opacity: 0.8,bumpScale: 10,roughness: 1,metalness: 0.0,})chinaItem.geometry.coordinates.forEach(chinaChildItem => {if (chinaItem.geometry.type === "MultiPolygon") {chinaChildItem.forEach((item) => {const oneCityShape = this.drawShape(item, [material2, material1])oneCityShapeArr.push(oneCityShape)})} else {const oneCityShape = this.drawShape(chinaChildItem, [material2, material1])oneCityShapeArr.push(oneCityShape)}})const newGeometry = this.mergeBufferGeometry(oneCityShapeArr)oneCityShape = new THREE.Mesh(newGeometry, [material2, material1])oneCityShape.name = chinaItem.properties.namethis.outlinePass.selectedObjects.push(oneCityShape)chinaGroup.add(oneCityShape)})chinaGroup.rotateX(-Math.PI/2)chinaGroup.scale.set(0.0015, 0.0015, 0.0015)this.scene.add(chinaGroup)}

拉伸shape任意几何体方法如下:

drawShape(position, material) {const pointArr = []const shape = new THREE.Shape()const extrudeSettings = {steps: 2,depth: 100000,curveSegments: 128,bevelEnabled: true,bevelThickness: 1,bevelSize: 1,bevelOffset: 10,bevelSegments: 1};position.forEach(point => {const coord = geographicToVector2(point)pointArr.push([coord[0]-center[0], coord[1] - center[1]]);})pointArr.forEach((p, i) => {i === 0 ? shape.moveTo(p[0], p[1]) : shape.lineTo(p[0], p[1])})const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings)return new THREE.Mesh(geometry, material)}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。