Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Kind of, yes, there are multiple options:</p> <ol> <li>via hierarchy You can simply add one mesh to another using the <code>add()</code> function</li> <li>via GeometryUtil's <code>merge()</code> function to merge vertices and meshes of two Geometry objects into one</li> <li>using a basic 3D editor that supports Boolean operations between meshes and exporting.</li> </ol> <p>Method 1 is pretty straight forward:</p> <pre><code>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); </code></pre> <p>Notice that 16 is repeated, so the subdivisions level in one mesh matches the other (for a decent look)</p> <p>Method 2.1 - via GeometryUtils</p> <pre><code>//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 &lt; 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); </code></pre> <p>Method 2.2 merging a <a href="https://stackoverflow.com/questions/8284233/three-js-custom-shapes/8284842#8284842">Lathe half-sphere</a> and a cylinder:</p> <pre><code>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 &lt; 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 &lt; 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); </code></pre> <p>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.</p> <p>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 <a href="http://www.blender.org/download/get-blender/" rel="nofollow noreferrer">Blender</a>(free, opensource), which already has a <a href="https://github.com/mrdoob/three.js/issues/143" rel="nofollow noreferrer">three.js</a> exporter. Alternatively you can export an .obj file of the merged meshes from your 3d editor or choice and use the <a href="https://github.com/mrdoob/three.js/blob/master/utils/exporters/convert_obj_three.py#L1" rel="nofollow noreferrer">convert_obj_three</a> script.</p> <p><strong>Update</strong></p> <p>I've found yet another method, which might be easier/more intuitive. Remember the boolean operations I've mentioned above ? </p> <p>Turns out there is an awesome js library just for that: <a href="https://github.com/evanw/csg.js" rel="nofollow noreferrer">Constructive Solid Geometry</a>: </p> <p><img src="https://i.stack.imgur.com/89GzB.png" alt="CSG library preview from owner&#39;s github page"></p> <p>Chandler Prall wrote some handy functions to connect <a href="http://chandler.prallfamily.com/2011/12/constructive-solid-geometry-with-three-js/" rel="nofollow noreferrer">CSG with three.js</a>. So with the CSG library and the <a href="http://chandler.prallfamily.com/labs/three/csg/ThreeCSG.js" rel="nofollow noreferrer">three.js wrapper for it</a>, you can simply do this:</p> <pre><code>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()); </code></pre> <p>Which gives you a nice result(no problems with extra faces/flipping normals/etc.):</p> <p><img src="https://i.stack.imgur.com/74dBj.png" alt="cylinder-sphere union with CSG and three.js"></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload