如何从路径或二维数组在 ThreeJS 中绘制墙壁?
How to draw walls in ThreeJS from path or 2d array?
我需要从我构建的 FabricJS
编辑器收到的 2d 路径或数组(稍后解释)绘制 3d 房屋模型(仅限墙壁)。从 2d 视图发送到 3d 视图的数据类型无关紧要。
我的第一个(也是非常接近我想要的)尝试是根据我想绘制的房间创建 1 和 0 的数组,然后在 ThreeJS 中将其渲染为每个 'grid'。我将此方法基于 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 的模型是可见的)。这是 more/less 它的样子:
(黑色 - 墙壁应该是什么样子,蓝色 - 墙壁的每个长方体,红色 - 一件家具)
这就是为什么我想将墙壁渲染为平面,可能来自 2d 封闭补丁(我可以毫无问题地从 Fabric 导出它)。当相机穿过墙壁时,我不需要墙壁很厚也不需要可见 "from behind"。关于如何实现这样的目标的任何线索?
"Help me Whosebug, your my only hope."
您可以手动填充 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());
我需要从我构建的 FabricJS
编辑器收到的 2d 路径或数组(稍后解释)绘制 3d 房屋模型(仅限墙壁)。从 2d 视图发送到 3d 视图的数据类型无关紧要。
我的第一个(也是非常接近我想要的)尝试是根据我想绘制的房间创建 1 和 0 的数组,然后在 ThreeJS 中将其渲染为每个 'grid'。我将此方法基于 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 的模型是可见的)。这是 more/less 它的样子:
这就是为什么我想将墙壁渲染为平面,可能来自 2d 封闭补丁(我可以毫无问题地从 Fabric 导出它)。当相机穿过墙壁时,我不需要墙壁很厚也不需要可见 "from behind"。关于如何实现这样的目标的任何线索?
"Help me Whosebug, your my only hope."
您可以手动填充 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());