如何从路径或二维数组中绘制ThreeJS中的墙?

时间:2016-02-16 15:10:03

标签: javascript 3d three.js fabricjs

我需要从我构建的FabricJS编辑器中的2d路径或数组(稍后解释)中绘制一个3d房屋模型(仅限墙壁)。从2d到3d视图发送的数据类型无关紧要。

我的第一个(并且非常接近我想要得到的)尝试是根据我想要绘制的房间创建1和0的数组,然后在ThreeJS中将其渲染为每个'网格'一个长方体。我基于this ThreeJS game demo这种方法。所以如果数组看起来像这样:

var map = [ //1  2  3  4  5  6  7  8
          [1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
          [1, 1, 0, 0, 0, 0, 0, 1, 1, 1,], // 1
          [1, 1, 0, 0, 1, 0, 0, 0, 0, 1,], // 2
          [1, 0, 0, 0, 1, 1, 0, 0, 0, 1,], // 3
          [1, 0, 0, 1, 1, 1, 1, 0, 0, 1,], // 4
          [1, 0, 0, 0, 1, 1, 0, 0, 1, 1,], // 5
          [1, 1, 1, 0, 0, 0, 0, 1, 1, 1,], // 6
          [1, 1, 1, 0, 0, 1, 0, 0, 1, 1,], // 7
          [1, 1, 1, 1, 1, 1, 0, 0, 1, 1,], // 8
          [1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
       ];

我遍历数组并为每个1渲染一个块,并从2d'map'(我的数组)的索引计算它的位置。

var UNITSIZE = 250, units = mapW;
for (var i = 0; i < mapW; i++) {
    for (var j = 0, m = map[i].length; j < m; j++) {
        if (map[i][j]) {
            var wall = new t.Mesh(cube, material);
            wall.position.x = (i - units/2) * UNITSIZE;
            wall.position.y = WALLHEIGHT/2;
            wall.position.z = (j - units/2) * UNITSIZE;
            scene.add(wall);
        }
    }
}

直到我想在墙附近放置其他模型(.obj,但无关紧要。让我们称之为furniture)之前,它一直很有用。每件家具在模型的中心都有(x=0, y=0, z=0)点,因为墙是立方体(具有相同的坐标系,中心有0点),所以家具在墙的中心呈现(当我们把它放在角落里,只有1/4的模型是可见的。这或多或少看起来像:

kitchen in 3d (黑色 - 墙壁应该是什么样的,蓝色 - 每个长方体的墙壁,红色的家具)

这就是为什么我想将墙作为平面渲染,可能是从2d封闭的补丁(我可以从Fabric中导出它而没有问题)。当相机穿过墙壁时,我不需要墙壁很厚,也不需要“从后面”看到。关于如何实现这样的事情的任何线索?

“帮我StackOverflow,这是我唯一的希望。”

1 个答案:

答案 0 :(得分:2)

您可以手动填充THREE.js网格的顶点和面数组,因此,如果您可以导出所需的闭合路径,例如作为坐标数组,您可以迭代它,并将所需信息推送到墙上对象

像这样的东西

var coordArray = [...]; //Array of corner points of a closed shape from your source. Here assumed to be THREE.Vector2() for simplicity.

var walls = new THREE.Geometry();

for(var i = 0; i < coordArray.length(); i++){ //iterate over the coordinate array, pushing vertices to the geometry
  var coordinates = coordArray[i];
  walls.vertices.push(new THREE.Vector3(coordinates.x, coordinates.y, 0)); //vertex at floor level
  walls.vertices.push(new THREE.Vector3(coordinates.x, coordinates.y, 10)); //vertex at the top part of the wall, directly above the last
}
var previousVertexIndex = walls.vertices.length - 2; // index of the vertex at the bottom of the wall, in the segment we are creating faces for
for(var i = 0; i < walls.vertices.length; i += 2){
  walls.faces.push(new THREE.Face3(i, i + 1, previousVertexIndex));
  walls.faces.push(new THREE.Face3(i + 1, previousVertexIndex + 1, previousVertexIndex));
  previousVertexIndex = i;
}
walls.computeVertexNormals();
walls.computeFaceNormals();

scene.add(new THREE.Mesh(walls, new THREE.MeshLambertMaterial());