如何在 THREE.JS 上创建自定义网格?

IT技术 javascript three.js
2021-03-14 18:26:33

我问过这个并得到了答案:

var geom = new THREE.Geometry(); 
var v1 = new THREE.Vector3(0,0,0);
var v2 = new THREE.Vector3(0,500,0);
var v3 = new THREE.Vector3(0,500,500);

geom.vertices.push(new THREE.Vertex(v1));
geom.vertices.push(new THREE.Vertex(v2));
geom.vertices.push(new THREE.Vertex(v3));

var object = new THREE.Mesh( geom, new THREE.MeshNormalMaterial() );
scene.addObject(object);

我预计这会奏效,但没有。

3个回答

您已经添加了顶点,但忘记将这些顶点放入面中并将其添加到几何体中:

geom.faces.push( new THREE.Face3( 0, 1, 2 ) );

所以你的片段变成:

var geom = new THREE.Geometry(); 
var v1 = new THREE.Vector3(0,0,0);
var v2 = new THREE.Vector3(0,500,0);
var v3 = new THREE.Vector3(0,500,500);

geom.vertices.push(v1);
geom.vertices.push(v2);
geom.vertices.push(v3);

geom.faces.push( new THREE.Face3( 0, 1, 2 ) );

var object = new THREE.Mesh( geom, new THREE.MeshNormalMaterial() );
scene.addObject(object);

这个想法是,Face3 实例通过使用列表/数组中顶点的索引来引用 3 个顶点(您之前添加到几何中的 x、y、z 坐标)。目前您只有 3 个顶点并且您想连接它们,因此您的脸在顶点数组中引用索引 0,1 和 2。

由于您使用的是网格法线材料,您可能需要计算几何体的法线。此外,请确保您的对象是可见的(不要太大或靠近要剪掉的相机,朝向正确的方向 - 朝向相机等)由于您是在 YZ 平面中绘制的,因此可以看到你的三角形,这样的事情应该工作:

var geom = new THREE.Geometry(); 
var v1 = new THREE.Vector3(0,0,0);
var v2 = new THREE.Vector3(0,500,0);
var v3 = new THREE.Vector3(0,500,500);

geom.vertices.push(v1);
geom.vertices.push(v2);
geom.vertices.push(v3);
                
geom.faces.push( new THREE.Face3( 0, 1, 2 ) );
geom.computeFaceNormals();
                
var object = new THREE.Mesh( geom, new THREE.MeshNormalMaterial() );
                
object.position.z = -100;//move a bit back - size of 500 is a bit big
object.rotation.y = -Math.PI * .5;//triangle is pointing in depth, rotate it -90 degrees on Y
                
scene.add(object);

更新: THREE.GeometryTHREE.Face3已弃用:THREE.BufferGeometry建议改为使用。

const geometry = new THREE.BufferGeometry();

const positions = [
0,   0, 0,    // v1
0, 500, 0,   // v2
0, 500, 500  // v3
];

geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
geometry.computeVertexNormals();

const object = new THREE.Mesh( geometry, new THREE.MeshNormalMaterial() );
scene.add(object);

简而言之,与提供顶点位置和具有 3 个顶点索引的 Face3 对象相反,现在您将按x1, y1, z1, x2, y2, z2, ..., xn, yn, zn顺序使用平面数组(每 3 个 x、y、z 三元组按顺序定义一个面)。

此外,还可以计算和提供顶点颜色和法线。有很多three.js示例可以开始,包括:

webgl_buffergeometry 三.js 三角形示例

webgl_buffergeometry_indexed 三.js 细分平面示例

哈哈,昨晚刚调试,结果.computeVertexNormals()必须调用,否则对象没有法线显示不正确颜色。
2021-04-28 18:26:33
嗯,THREE.Geometry几年后被弃用了..主要是为了性能discourse.threejs.org/t/...
2021-05-09 18:26:33
@jiyinyiyong 谢谢你!我发布这个答案已经有一段时间了:) 我添加了一些最小的注释。
2021-05-21 18:26:33

您可以自动进行三角测量

对于大多边形,手动添加面可能是一项艰巨的工作。您可以使用如下triangulateShape方法THREE.ShapeUtils自动将面添加到网格的过程

var vertices = [your vertices array];
var holes = [];
var triangles, mesh;
var geometry = new THREE.Geometry();
var material = new THREE.MeshBasicMaterial();

geometry.vertices = vertices;

triangles = THREE.ShapeUtils.triangulateShape( vertices, holes );

for( var i = 0; i < triangles.length; i++ ){

    geometry.faces.push( new THREE.Face3( triangles[i][0], triangles[i][1], triangles[i][2] ));

}

mesh = new THREE.Mesh( geometry, material );

vertices您的顶点数组在哪里holes您可以在多边形中定义孔。

注意:小心,如果你的多边形是自相交的,它会抛出一个错误。确保您的顶点数组表示有效(非相交)多边形。

@GamsterKatalin 三角剖分仅适用于 2D 形状。目前,您在 javascript 中找不到任何适用于 3D 的三角剖分库。你将不得不解决。一种解决方案是使用旋转矩阵将您的 3D 形状旋转到 xy 平面,然后使用逆矩阵对结果进行三角测量和旋转。
2021-04-21 18:26:33
这种方法似乎完全忽略了 Z 轴,仅适用于 2D。根本不适用于 3d 顶点。
2021-05-02 18:26:33
THREE.Shape.Utils.triangulateShape 不工作了。
2021-05-03 18:26:33
您的答案不会自动对 3d 顶点进行三角剖分(给我很多警告,因为 xy 点重复,三角剖分最终失败),所以现在我试图找出生成 face3 的索引点背后的基本原理来自:github.com/josdirksen/learning-threejs/blob/master/chapter-02/...考虑到它们是来自 autocad 对象的数百个顶点。
2021-05-09 18:26:33
@GamsterKatalin 检查我更新的答案。在较新的版本中,它是:THREE.ShapeUtils.triangulateShape.
2021-05-15 18:26:33

THREE.Vertex 在 Three.js 的最新版本中已被弃用,因此不再需要该部分:

geom.vertices.push(v1);
geom.vertices.push(v2);
geom.vertices.push(v3);
请注意,这是指 George Profenza 答案的早期修订版。不应从 Profenza 的当前代码中删除任何内容。
2021-05-18 18:26:33