关于webgl:webglthreejs生成房间楼层

2次阅读

共计 3107 个字符,预计需要花费 8 分钟才能阅读完成。

楔子

在很多数字孪生我的项目中,都会波及到楼层的建模。楼层的建模因为构造繁多,如果都是建模师进行手动建模,工作量会比拟大。而楼层自身的构造,能够形象成能够通过门路结构的对象 (这和之前的文章提及的的管路以及路线相似),这不便咱们通过代码的形式来生成房间楼层。

墙体几何对象 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 彪叔”能够增加作者微信进行交换,及时收到更多有价值的文章。

正文完
 0