如何在 THREE.JS 上创建自定义网格?
Posted
技术标签:
【中文标题】如何在 THREE.JS 上创建自定义网格?【英文标题】:How to create a custom mesh on THREE.JS? 【发布时间】:2012-03-04 09:31:44 【问题描述】:我已经问过这个问题并得到了答案:
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);
我希望这会起作用,但它没有。
【问题讨论】:
我知道这个问题很老但仅供参考 this article 和 this one 涵盖这个主题 【参考方案1】:您已添加顶点,但忘记将这些顶点放入面并将其添加到几何体中:
geom.faces.push( new THREE.Face3( 0, 1, 2 ) );
所以你的 sn-p 变成:
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.Geometry
和 THREE.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 webgl_buffergeometry_indexed【讨论】:
好吧,THREE.Geometry
在几年后被弃用了.. 主要是为了提高性能discourse.threejs.org/t/…
@jiyinyiyong 谢谢你!自从我发布这个答案以来已经有一段时间了:) 我添加了一些简单的注释。
哈哈,昨晚刚调试了一下,原来.computeVertexNormals()
必须被调用,否则没有法线,物体就无法正确显示颜色。【参考方案2】:
THREE.Vertex 在最新版本的 Three.js 中已被弃用,因此不再需要该部分:
geom.vertices.push(v1);
geom.vertices.push(v2);
geom.vertices.push(v3);
【讨论】:
请注意,这是指 George Profenza 答案的早期版本。 Profenza 的当前代码中不应删除任何内容。【参考方案3】:您可以自动进行三角测量
对于大多边形,手动添加面可能是一项艰巨的工作。您可以使用the triangulateShape
method in 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
您可以在多边形中定义孔。
注意:小心,如果你的多边形是自相交的,它会抛出一个错误。确保您的顶点数组代表一个有效的(非相交的)多边形。
【讨论】:
此方法似乎完全忽略了 Z 轴,并且仅适用于 2D。根本不适用于 3d 顶点。THREE.Shape.Utils.triangulateShape
不再起作用了。
@GamsterKatalin 检查我更新的答案。在较新的版本中,它是:THREE.ShapeUtils.triangulateShape
.
您的答案不会自动对 3d 顶点进行三角剖分(给我很多警告,因为 xy 点重复,三角剖分最终失败),所以现在我试图找出生成背后的基本原理face3 构建的那些索引点:github.com/josdirksen/learning-threejs/blob/master/chapter-02/… 考虑到它们是来自 AutoCAD 对象的数百个顶点。
@GamsterKatalin Triangulation 仅适用于 2D 形状。目前,您不会在 javascript 中找到任何在 3D 中工作的三角测量库。你将不得不解决。一种解决方案是使用旋转矩阵将 3D 形状旋转到 x-y 平面,然后使用逆矩阵对结果进行三角剖分和旋转。以上是关于如何在 THREE.JS 上创建自定义网格?的主要内容,如果未能解决你的问题,请参考以下文章
three.js - 使用 MeshLambertMaterial 和点光源绘制自定义网格