Three.js -2つの形状を1つとして結合しますか?
-
26-10-2019 - |
質問
私はThree.jsの世界に慣れていません...私の質問は次のとおりです。2つの異なる形を1つの形状として結合できますか?たとえば、球とシリンダーを1つとして結合しますか?
解決
はい、複数のオプションがあります。
- 階層を介して、1つのメッシュを別のメッシュに追加するだけで、
add()
関数 - Geometryutilを経由して
merge()
2つのジオメトリオブジェクトの頂点とメッシュを1つにマージする機能 - メッシュとエクスポートの間のブール操作をサポートする基本的な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マージa 旋盤半球 そしてシリンダー:
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)をマージします)。シリンダーと球体を作成してみてください ブレンダー(無料、opensource)、すでに 3.js 輸出業者。または、3Dエディタまたは選択からマージされたメッシュの.OBJファイルをエクスポートして、 convert_obj_three 脚本。
アップデート
私はさらに別の方法を見つけましたが、それはより簡単/より直感的かもしれません。上記のブール操作を覚えていますか?
そのためだけに素晴らしいJSライブラリがあることがわかりました: 建設的な固体ジオメトリ:
Chandler Prallは、接続する便利な機能をいくつか書きました Three.jsのCSG. 。したがって、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());
それはあなたに素晴らしい結果をもたらします(余分な顔/フリッピング正規/などに問題はありません。):
他のヒント
Three.js R62のラッパーを更新しました。ここで見つけることができます。 https://github.com/kraag22/csg-wrapper