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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:34:02  来源:igfitidea点击:

Three.js - bind two shapes together as one?

javascript3dthree.js

提问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:

是的,有多种选择:

  1. via hierarchy You can simply add one mesh to another using the add()function
  2. via GeometryUtil's merge()function to merge vertices and meshes of two Geometry objects into one
  3. using a basic 3D editor that supports Boolean operations between meshes and exporting.
  1. 通过层次结构您可以使用该add()功能简单地将一个网格添加到另一个网格
  2. 通过 GeometryUtil 的merge()函数将两个 Geometry 对象的顶点和网格合并为一个
  3. 使用支持网格和导出之间的布尔运算的基本 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 库就是为了这个:构造实体几何

CSG library preview from owner's github page

来自所有者 github 页面的 CSG 库预览

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.):

这给了你一个很好的结果(额外的面/翻转法线/等没有问题):

cylinder-sphere union with CSG and three.js

使用 CSG 和 Three.js 的圆柱球体联合

回答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