Three.js - 将两个形状绑定为一个?

时间:2011-11-30 08:00:31

标签: javascript 3d three.js

我是three.js世界的新手...... 我的问题是:我可以将两种不同的形状绑定在一起作为一个形状吗? 例如,将球体和圆柱体绑定在一起?

2 个答案:

答案 0 :(得分:42)

有,是的,有多种选择:

  1. via hierarchy您可以使用add()函数
  2. 简单地将一个网格添加到另一个网格
  3. 通过GeometryUtil的merge()函数将两个Geometry对象的顶点和网格合并为一个
  4. 使用支持网格和导出之间的布尔运算的基本3D编辑器。
  5. 方法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);
    

    请注意,16会重复,因此一个网格中的细分级别与另一个网格中的细分级别相匹配(为了看起来不错)

    方法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);
    

    方法2.2合并Lathe half-sphere和圆柱体:

    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);
    

    目前我无法解决的一个问题来自网格内部的面。理想情况下,那些会翻转法线以便它们不会渲染,但是没有找到快速解决方案。

    第三是相当直接的。大多数3D软件包允许对网格进行布尔运算(例如,将两个网格与ADD运算(meshA + meshB)合并在一起)。尝试在Blender(free,opensource)中创建一个圆柱体和一个球体,它已经有一个three.js导出器。或者,您可以从3d编辑器或选项中导出合并网格的.obj文件,并使用convert_obj_three脚本。

    <强>更新

    我发现了另一种方法,可能更容易/更直观。还记得我上面提到的布尔运算吗?

    原来有一个非常棒的js库:Constructive Solid Geometry

    CSG library preview from owner's github page

    Chandler Prall写了一些方便的函数来连接CSG with three.js。因此,使用CSG库和three.js wrapper for it,您只需执行此操作:

    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());
    

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

    cylinder-sphere union with CSG and three.js

答案 1 :(得分:6)

我更新了THREE.js r62的包装器,你可以在这里找到它:https://github.com/kraag22/csg-wrapper