Three.js - 将两个形状绑定在一起? [英] Three.js - bind two shapes together as one?

查看:40
本文介绍了Three.js - 将两个形状绑定在一起?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

是的,有多种选择:

  1. 通过层次结构您可以使用add() 函数将一个网格添加到另一个网格中
  2. 通过 GeometryUtil 的 merge() 函数将两个 Geometry 对象的顶点和网格合并为一个
  3. 使用支持网格和导出之间的布尔运算的基本 3D 编辑器.

方法 1 非常简单:

var sphere = new THREE.Mesh( new THREE.SphereGeometry(100,16,12),new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));var圆柱=新THREE.Mesh(new THREE.CylinderGeometry(100, 100, 200, 16, 4, false ),new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));气缸位置 y = -100;场景添加(球体);场景添加(圆柱体);

注意 16 是重复的,所以一个网格中的细分级别与另一个匹配(为了看起来不错)

方法 2.1 - 通过 GeometryUtils

//制作一个球体var sg = new THREE.SphereGeometry(100,16,12);//制作圆柱体 - 理想情况下,分割类似于可预测的结果var cg = new THREE.CylinderGeometry(100, 100, 200, 16, 4, false );//向下移动圆柱体的顶点,使其达到球体的一半 - 偏移枢轴for(var i = 0 ; i < cg.vertices.length; i++) cg.vertices[i].position.y -= 100;//合并网格三.GeometryUtils.merge(sg,cg);var mesh = new THREE.Mesh( sg,new THREE.MeshLambertMaterial( { color: 0x2D303D, wireframe: true, shading: THREE.FlatShading } ));场景.添加(网格);

方法 2.2 合并一个.因此,使用 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几何=圆柱体.联合(球体);var mesh = new THREE.Mesh(THREE.CSG.fromCSG( geometry),new THREE.MeshNormalMaterial());

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

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?

解决方案

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.

Method 1 is pretty straight forward:

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)

Method 2.1 - via 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-sphere and a cylinder:

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.js exporter. Alternatively you can export an .obj file of the merged meshes from your 3d editor or choice and use the convert_obj_three script.

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:

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:

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

这篇关于Three.js - 将两个形状绑定在一起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆