Javascript Three.js - 将两个形状绑定在一起?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8322759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Three.js - bind two shapes together as one?
提问by BorisD
I'm new to the three.js world... My question is: Can I bind two different shapes together as one shape? For example binding sphere and cylinder together as one?
我是 Three.js 世界的新手……我的问题是:我可以将两个不同的形状绑定在一起作为一个形状吗?例如将球体和圆柱体绑定在一起?
回答by George Profenza
Kind of, yes, there are multiple options:
是的,有多种选择:
- via hierarchy You can simply add one mesh to another using the
add()
function - via GeometryUtil's
merge()
function to merge vertices and meshes of two Geometry objects into one - using a basic 3D editor that supports Boolean operations between meshes and exporting.
- 通过层次结构您可以使用该
add()
功能简单地将一个网格添加到另一个网格 - 通过 GeometryUtil 的
merge()
函数将两个 Geometry 对象的顶点和网格合并为一个 - 使用支持网格和导出之间的布尔运算的基本 3D 编辑器。
Method 1 is pretty straight forward:
方法 1 非常简单:
var sphere = new THREE.Mesh( new THREE.SphereGeometry(100,16,12),new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));
var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(100, 100, 200, 16, 4, false ),new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));
cylinder.position.y = -100;
scene.add(sphere);
scene.add(cylinder);
Notice that 16 is repeated, so the subdivisions level in one mesh matches the other (for a decent look)
请注意,16 是重复的,因此一个网格中的细分级别与另一个匹配(为了看起来不错)
Method 2.1 - via GeometryUtils
方法 2.1 - 通过 GeometryUtils
//make a sphere
var sg = new THREE.SphereGeometry(100,16,12);
//make cylinder - ideally the segmentation would be similar to predictable results
var cg = new THREE.CylinderGeometry(100, 100, 200, 16, 4, false );
//move vertices down for cylinder, so it maches half the sphere - offset pivot
for(var i = 0 ; i < cg.vertices.length; i++) cg.vertices[i].position.y -= 100;
//merge meshes
THREE.GeometryUtils.merge(sg,cg);
var mesh = new THREE.Mesh( sg,new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));
scene.add(mesh);
Method 2.2 merging a Lathe half-sphereand a cylinder:
方法 2.2 合并一个车床半球和一个圆柱体:
var pts = [];//points array
var detail = .1;//half-circle detail - how many angle increments will be used to generate points
var radius = 100;//radius for half_sphere
var total = Math.PI * .51;
for(var angle = 0.0; angle < total ; angle+= detail)//loop from 0.0 radians to PI (0 - 180 degrees)
pts.push(new THREE.Vector3(0,Math.cos(angle) * radius,Math.sin(angle) * radius));//angle/radius to x,z
var lathe = new THREE.LatheGeometry( pts, 16 );//create the lathe with 12 radial repetitions of the profile
//rotate vertices in lathe geometry by 90 degrees
var rx90 = new THREE.Matrix4();
rx90.setRotationFromEuler(new THREE.Vector3(-Math.PI * .5,0,0));
lathe.applyMatrix(rx90);
//make cylinder - ideally the segmentation would be similar for predictable results
var cg = new THREE.CylinderGeometry(100, 100, 200, 16, 4, false );
//move vertices down for cylinder, so it maches half the sphere
for(var i = 0 ; i < cg.vertices.length; i++) cg.vertices[i].position.y -= 100;
//merge meshes
THREE.GeometryUtils.merge(lathe,cg);
var mesh = new THREE.Mesh( lathe, new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ) );
mesh.position.y = 150;
scene.add(mesh);
The one problem I can't address at the moment comes from the faces that are inside the mesh. Ideally those would have normals flipped so they wouldn't render, but haven't found a quick solution for that.
我目前无法解决的一个问题来自网格内部的面。理想情况下,那些法线会翻转,因此它们不会渲染,但还没有找到快速解决方案。
The 3rd is fairly straight forward. Most 3D packages allow Boolean operation on meshes (e.g. merging two meshes together with the ADD operation (meshA + meshB)). Try creating a cylinder and a sphere in Blender(free, opensource), which already has a three.jsexporter. Alternatively you can export an .obj file of the merged meshes from your 3d editor or choice and use the convert_obj_threescript.
第三个是相当直接的。大多数 3D 软件包允许对网格进行布尔运算(例如,将两个网格与 ADD 操作合并在一起(meshA + meshB))。尝试在Blender(免费,开源)中创建一个圆柱体和一个球体,它已经有一个Three.js导出器。或者,您可以从 3d 编辑器或选择导出合并网格的 .obj 文件并使用convert_obj_three脚本。
Update
更新
I've found yet another method, which might be easier/more intuitive. Remember the boolean operations I've mentioned above ?
我发现了另一种方法,它可能更容易/更直观。还记得我上面提到的布尔运算吗?
Turns out there is an awesome js library just for that: Constructive Solid Geometry:
原来有一个很棒的 js 库就是为了这个:构造实体几何:
Chandler Prall wrote some handy functions to connect CSG with three.js. So with the CSG library and the three.js wrapper for it, you can simply do this:
Chandler Prall 编写了一些方便的函数来将CSG 与three.js连接起来。因此,使用 CSG 库和它的three.js 包装器,您可以简单地执行以下操作:
var cylinder = THREE.CSG.toCSG(new THREE.CylinderGeometry(100, 100, 200, 16, 4, false ),new THREE.Vector3(0,-100,0));
var sphere = THREE.CSG.toCSG(new THREE.SphereGeometry(100,16,12));
var geometry = cylinder.union(sphere);
var mesh = new THREE.Mesh(THREE.CSG.fromCSG( geometry ),new THREE.MeshNormalMaterial());
Which gives you a nice result(no problems with extra faces/flipping normals/etc.):
这给了你一个很好的结果(额外的面/翻转法线/等没有问题):
回答by kraag22
I updated wrapper for THREE.js r62, you can find it here: https://github.com/kraag22/csg-wrapper
我更新了 THREE.js r62 的包装器,你可以在这里找到它:https: //github.com/kraag22/csg-wrapper