中国空间站设计在轨飞行多少年,无锡所有网站设计制作,seo顾问服务四川,企业微信管理客户翻到了之前的一个案例#xff0c;基于three.js做的仓库布局模拟#xff0c;地图元素除了大模型外#xff0c;其他都是通过JSON数据解析动态生成的#xff0c;例如墙体#xff0c;柱子门口#xff0c;地标等#xff0c;集成了第一人称的插件可以第一人称进入场景有需要的…
翻到了之前的一个案例基于three.js做的仓库布局模拟地图元素除了大模型外其他都是通过JSON数据解析动态生成的例如墙体柱子门口地标等集成了第一人称的插件可以第一人称进入场景有需要的可以下载看看对想入门的朋友应该有一些参考价值。 /** *创建自定义几何体 *输入参数几何体底面逆时针坐标组、几何体高度 * 目前只支持凸多边形 逆时针则连线顺时针不连线 */
function createCustomBufferGeometry(planeArr, height, color) { let planes planeArr; let planes2 []; //组装顶面坐标 for (let i 0; i planes.length; i) { planes2.push(new THREE.Vector3(planes[i].x, planes[i].y height, planes[i].z)); } planes planes.concat(planes2); let arr []; //循环组成三角面 for (let i 0; i planes.length; i) { let j i 1, k2 j planes2.length; let xLength planes2.length; if (j planes2.length i planes2.length) { j 0; k2 j planes2.length; } if (i planes2.length) { if (j planes.length) { j planes2.length; } k2 i - planes2.length; xLength planes.length; } for (let x i 2; x xLength; x) { arr arr.concat([planes[i].x, planes[i].y, planes[i].z]); arr arr.concat([planes[j].x, planes[j].y, planes[j].z]); arr arr.concat([planes[x].x, planes[x].y, planes[x].z]); // if (((planes[j].x - planes[i].x) * (planes[x].z - planes[i].z) - (planes[x].x - planes[i].x) * ( planes[j].z - planes[i].z)) 0) { // arr arr.concat([planes[i].x, planes[i].y, planes[i].z]); // arr arr.concat([planes[j].x, planes[j].y, planes[j].z]); // arr arr.concat([planes[x].x, planes[x].y, planes[x].z]); // } } arr arr.concat([planes[i].x, planes[i].y, planes[i].z]); if (i planes2.length) { arr arr.concat([planes[j].x, planes[j].y, planes[j].z]); arr arr.concat([planes[k2].x, planes[k2].y, planes[k2].z]); } else { arr arr.concat([planes[k2].x, planes[k2].y, planes[k2].z]); arr arr.concat([planes[j].x, planes[j].y, planes[j].z]); } } let bufferGeometry new THREE.BufferGeometry(); let vertices new Float32Array(arr); // itemSize 3 因为每个顶点都是一个三元组。 bufferGeometry.addAttribute(position, new THREE.BufferAttribute(vertices, 3)); bufferGeometry.computeFaceNormals();//计算法向量会对光照产生影响 bufferGeometry.computeVertexNormals();//自动设置法向量 let material new THREE.MeshLambertMaterial({ color: color }); let mesh new THREE.Mesh(bufferGeometry, material); _bufferGeometry bufferGeometry; //worldScene.add(mesh); return mesh;
}
var _bufferGeometry;
/** *地图数据坐标是左上角为原点开始的二维坐标系x,y绘制以左上角开始 * web 3d坐标原点是屏幕中心点绘制的时候也是以中心为相对位置 * MapXLength地图最长距离MapZLength 地图最宽距离 * 转换规则 3d.position.x 2d.width/2 - maxWidth/2 2d.position.x * 3d.position.z 2d.height/2 - maxHeight/2 2d.position.z; * 3d.position.y y轴高度 2D地图无需设置,默认为0,如果有高度, 3d.position.y 2d.高度.y/22d.高度位置MapYLength/2 */
function handCoordinate(data) { data.x data.x / 10; data.y data.y / 10; data.z data.z / 10; if (data.positionY) data.positionY data.positionY / 10; else data.positionY 0; data.width data.width / 10; data.height data.height / 10; data.x data.width / 2 - MapXLength / 2 data.x; data.z data.height / 2 - MapZLength / 2 data.z; if (data.groupOption) { data.groupOption.offSetX data.groupOption.offSetX / 10; data.groupOption.offSetY data.groupOption.offSetY / 10; data.groupOption.offSetZ data.groupOption.offSetZ / 10; }
}
var _baseBox;
var _floorType;
//最底层的box
function createBaseBox(data,floorType) { data.width data.width / 10; data.height data.height / 10; MapXLength data.width; MapZLength data.height; sizeRatio MapXLength / MapXLength; if(data.floorType){ _floorType data.floorType; if(!floorModels[floorType]) { floorModels[floorType] []; } } var geometry new THREE.BoxBufferGeometry(data.width, 1, data.height); var material new THREE.MeshLambertMaterial({ color: data.color }); var cube new THREE.Mesh(geometry, material); cube.position.set(0, 0, 0); //cube.castShadow true;//开启投影 cube.receiveShadow true;//接收阴影 cube.geometry.computeBoundingBox(); _baseBox cube.geometry.boundingBox; clickObjects.push(cube);//加入点击对象组 worldScene.add(cube); floorModels[floorType].push(cube); //console.log(cube); //地图标注 // worldScene.add(createTextTextureBySprite(data))
}
//创建几何体
function createBox(data,_floorType) { handCoordinate(data); var geometry new THREE.BoxGeometry(data.width, data.y, data.height); var material new THREE.MeshLambertMaterial({ color: data.color, vertexColors: THREE.FaceColors }); var cube new THREE.Mesh(geometry, material); cube.castShadow true;//开启投影 //cube.receiveShadow true;//接收阴影 cube.position.set(data.x, 0.55 data.positionY / 2 data.y / 2, data.z); var newMesh; //几何体组合处理 if (data.bspMesh) { newMesh cube; data.bspMesh.forEach(x { handCoordinate(x); let tempMesh; if (x.geometryType box) { tempGeometry new THREE.BoxGeometry(x.width, x.y, x.height); tempMesh new THREE.Mesh(tempGeometry, new THREE.MeshLambertMaterial({ color: x.color })); } tempMesh.position.set(x.x, 0.55 x.positionY / 2 x.y / 2, x.z); newMesh bspMesh(x.type, newMesh, tempMesh); }) } else { } let finalMesh; if (newMesh) { newMesh.castShadow true;//开启投影 // worldScene.add(newMesh); finalMesh newMesh; } else { finalMesh cube; // worldScene.add(cube); } //多个相同模型组合 if (data.type data.type group) { for (let i 0; i data.groupOption.total; i) { let tempMesh finalMesh.clone(); if (data.groupOption.offSetX ! 0) { tempMesh.position.x finalMesh.position.x (data.width data.groupOption.offSetX) * i; } if (data.groupOption.offSetY ! 0) { tempMesh.position.y finalMesh.position.y (data.y data.groupOption.offSety) * i; } if (data.groupOption.offSetZ ! 0) { tempMesh.position.z finalMesh.position.z (data.height data.groupOption.offSetZ) * i; } // tempMesh.position.set( // ( data.widthtempMesh.position.xdata.groupOption.offSetX)*i, // ( data.ytempMesh.position.ydata.groupOption.offSetY)*i, // (data.heighttempMesh.position.zdata.groupOption.offSetZ)*i); worldScene.add(tempMesh); floorModels[_floorType].push(tempMesh); } } else { worldScene.add(finalMesh); floorModels[_floorType].push(finalMesh); } //地图标注 let sprite createTextureBySprite(data); if (sprite ! null) worldScene.add(sprite);
} //创建圆柱体
function createCylinder(data) { handCoordinate(data); var geometry new THREE.CylinderGeometry(data.width / 2, data.width / 2, data.y, 32); var material new THREE.MeshLambertMaterial({ color: data.color, vertexColors: THREE.FaceColors }); var cylinder new THREE.Mesh(geometry, material); cylinder.position.set(data.x, 0.55 data.positionY / 2 data.y / 2, data.z); for (let i 0; i 64; i) { geometry.faces[i].color new THREE.Color(#004892); } worldScene.add(cylinder);
} /** * 创建网格 * param {几何体对象} geometry */
function createMesh(geometry, color) { if (!color) { color #4685C6; } return new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({ color: color })); } /** * A,B模型type:intersect 交集 union 并集 subtract 差集 * param {A模型} geometryA * param {B模型} geometryB */
function bspGeometry(type, geometryA, geometryB) { //生成ThreeBSP对象 var a new ThreeBSP(geometryA); var b new ThreeBSP(geometryB); //进行算 var resultBSP; if (type intersect) resultBSP a.intersect(b); else if (type union) resultBSP a.union(b); else resultBSP a.subtract(b); //从BSP对象内获取到处理完后的mesh模型数据 var result resultBSP.toGeometry(); //更新模型的面和顶点的数据 result.computeFaceNormals(); result.computeVertexNormals(); return cresult; } /** * A,B模型type:intersect 交集 union 并集 subtract 差集 * param {A模型} meshA * param {B模型} meshB */
function bspMesh(type, meshA, meshB) { //生成ThreeBSP对象 var a new ThreeBSP(meshA); var b new ThreeBSP(meshB); //进行算 var resultBSP; if (type intersect) resultBSP a.intersect(b); else if (type union) resultBSP a.union(b); else resultBSP a.subtract(b); //从BSP对象内获取到处理完后的mesh模型数据 var result resultBSP.toMesh(); result.material meshA.material; //更新模型的面和顶点的数据 result.geometry.computeFaceNormals(); result.geometry.computeVertexNormals(); testResult result return result; }
var testResult; /** *创建地图标注 *canvas地图标注的内容很小需要放大放大会失真后期调整其缩放大小或者不采用canvas渲染 */
function createTextureBySprite(data) { if ((data.title data.imageurl ) || (!data.title !data.imageurl)) { return null; } let canvas document.createElement(canvas); canvas.width3000; canvas.height2000; let ctx canvas.getContext(2d); ctx.lineWidth 1; ctx.textAlign center; ctx.textBaseline middle; ctx.textAlign center; if (data.font) { ctx.font data.font; } else { ctx.font Normal 180px Arial } if (data.textcolor) { ctx.fillStyle data.textcolor; } //ctx.lineWidth 4; if (data.imageurl) { let img new Image(); img.src data.imageurl; img.onload function () { ctx.drawImage(img, 30, 90); texture.needsUpdate true; } } /* 把整个 canvas 作为纹理所以字尽量大一些撑满整个 canvas 画布。 但也要小心文字溢出画布。 */ ctx.fillText(data.title, 400, 200); let texture new THREE.CanvasTexture(canvas); let material new THREE.SpriteMaterial({ map: texture, transparent: true, // 避免遮挡其他图形 // sizeAttenuation:false }); let textMesh new THREE.Sprite(material); /* 精灵很小要放大 */ textMesh.scale.set(10, 10, 10); /* WebGL 3D 世界中的位置 */ textMesh.position.set(data.x,data.y 1.5, data.z);//data.y 3 return textMesh;
}