楔子
在很多数字孪生我的项目中,都会波及到楼层的建模。楼层的建模因为构造繁多,如果都是建模师进行手动建模,工作量会比拟大。而楼层自身的构造,能够形象成能够通过门路结构的对象(这和之前的文章提及的的管路以及路线相似),这不便咱们通过代码的形式来生成房间楼层。
墙体几何对象PathCubeGeometry
楼层个别分成墙体和地板两个局部,首先来看下墙体对象。 以threejs为根底,扩大一个几何对象PathCubeGeometry。 该对象通过一个Path3D门路来结构一个墙的几何体,该几何体能够分成start,end,top,bottom,outside,inside等几个外表分组,这样就不便给内外表和外外表,以及顶面等设置不同的材质贴图的成果。 次要代码如下:
this.vert = vert; this.rawUV = rawUV; this.pathU = pathU; this.indices = [] this.vertices = []; this.uvs = [], this.normals = []; this.generateSideWall(vert,inner,outer,innerTop, outerTop, true,closed); this.generateSideWall(vert,inner,outer,innerTop, outerTop, false,closed); this.generateTopBottom(vert,inner,outer,innerTop,outerTop,true,closed); this.generateTopBottom(vert,inner,outer,innerTop,outerTop,false,closed); if(!closed) { this.generateAZSide(vert,inner,outer,innerTop,outerTop,true); this.generateAZSide(vert,inner,outer,innerTop,outerTop,false); }
通过PathCubeGeometry,咱们能够不便的构建墙体,比方如下示例代码:
const materials = [m1, m2, m3, m3, m3, m3];const points = json.outerWall.path;const p0 = points[0];const path = new Path3D();const scale = 20;path.moveTo(p0.x * scale, p0.y * scale, p0.z * scale);for (let i = 1; i < points.length; i++) {let p = points[i]; path.lineTo(p.x * scale, p.y * scale, p.z * scale);}path.closePath();cosnt patCube = new PathCubeGeometry(path, 10, 50, 32, 500);const mesh = new dt.Mesh(patCube, materials);
首先通过Path3D结构一个门路(门路来源于传入的一系列点points),而后通过门路结构一个结合体对象PathCubeGeometry,最初生成实体,成果如下图所示:
门和窗
结构门和窗的难度不大,个别都通过立方体 + 贴图的形式就能够生成。比方如下代码能够生成一个双开门:
function createDoor(pos) { var cube = new CubeGeometry(200, 400, 5); var material = createMaterial(graph, { color: 0xffffff, flatShading: true, map: "./images/glass-wall6.png", transparent: true, }); material.map.repeat.set(0.5, 1); var leftDoor = new Mesh(cube, material); leftDoor.position.copy(pos.clone().sub(new Vec3(100))); leftDoor.attr("type", "left_door"); leftDoor._type = "left_door"; dataModel.add(leftDoor); var rightDoor = new Mesh(cube, material); rightDoor.position.copy(pos.clone().add(new Vec3(100))); rightDoor._type = "right_door"; dataModel.add(rightDoor);}
创立的门的成果如下图所示:
创立单开门和窗户的思路是统一的。不过难点的中央是门窗所在的地位,墙体自身须要挖洞。挖洞须要应用BSP性能。
BSP挖洞
BSP操作能够对模型进行交加 并集 差集的操作。 要在墙上挖洞,能够在墙的几何体上进行差集操作,比方减去一个立方体,这样就能够在墙面上生成一个方型的洞。
在THREEJS下面,有一个开源的BSP包,THREEBSP。
代码如下所示:
var csg = new CSG().setFromGeometry(patCube);var csg2 = new CSG().setFromGeometry(cubeGeometry);var csg3 = new CSG().setFromGeometry(cubeGeometry2);csg.subtractOperand(csg2);csg.subtractOperand(csg3);var geometry = csg.toGeometry();var mesh = new Mesh(geometry, materials);
最初生成的成果如下图所示:
在把创立好的门和窗放到相应的挖洞地位,成果如下所示:
创立地板
在threejs中,通过ExtrudeGeometry能够创立地板的几何体,而后指定地板的材质,既能够创立一个地板对象 代码如下所示:
var path = new ShapePath(); var texture = graph.loadTexture("./images/floor.jpg", { wrapT: RepeatWrapping, wrapS: RepeatWrapping, }); texture.repeat.set(1 / 400, 1 / 400); texture.anisotropy = 16; let m1 = new BasicMaterial({ map: texture, color: 0xffffff, toneMapped: false, }); const simpleShapes = path.toShapes(true); var geometry = new ExtrudeGeometry(simpleShapes, { depth: 1, bevelEnabled: false, vertical: true, }); var mesh = new Mesh(geometry, [m1, m1]); dataModel.add(mesh);
最终的成果如下所示:
结语
本文介绍了通过代码生成楼层的性能,其中用到了PathCubeGeometry,ExtrudeGeometry,BSP相干技术,其中PathCubeGeometry因为须要本人构建,会稍晚难点; ExtrudeGeometry是threejs自身就存在的对象,BSP也能够找到开源的包能够应用。
如果你有好的思路,也欢送和我交换。关注公号“ITMan彪叔” 能够增加作者微信进行交换,及时收到更多有价值的文章。