web-dev-qa-db-ja.com

Three.js-2つのシェイプを1つにバインドしますか?

私はthree.jsの世界に不慣れです...私の質問は:2つの異なる形状を1つの形状として結合できますか?たとえば、球と円柱を1つにまとめますか?

21
BorisD

はい、複数のオプションがあります。

  1. 階層を介してadd()関数を使用して1つのメッシュを別のメッシュに簡単に追加できます
  2. geometryUtilのmerge()関数を使用して、2つのGeometryオブジェクトの頂点とメッシュを1つにマージします
  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 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 旋盤半球 と円柱をマージする:

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

現時点で対処できない問題の1つは、メッシュの内側にある面にあります。理想的には、法線が反転してレンダリングされないようにしますが、そのための迅速な解決策は見つかりませんでした。

3番目はかなり簡単です。ほとんどの3Dパッケージでは、メッシュのブール演算が可能です(たとえば、2つのメッシュをADD演算(meshA + meshB)とマージする)。 Blender (free、opensource)で円柱と球を作成してみてください。すでに three.js エクスポーターがあります。または、マージされたメッシュの.objファイルを3Dエディターまたは選択からエクスポートして、 convert_obj_three スクリプトを使用することもできます。

更新

私はさらに別の方法を見つけました。それはより簡単でより直感的かもしれません。上で述べたブール演算を覚えていますか?

そのためだけに素晴らしいjsライブラリがあることがわかりました: Constructive Solid Geometry

CSG library preview from owner's github page

Chandler Prallは、接続するためのいくつかの便利な関数を作成しました CSG with 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());

これはあなたに素晴らしい結果を与えます(余分な顔/法線の反転などの問題はありません):

cylinder-sphere union with CSG and three.js

42
George Profenza

THREE.js r62のラッパーを更新しました。ここで見つけることができます: https://github.com/kraag22/csg-wrapper

6
kraag22