Pregunta

Soy nuevo en el mundo tres.js ... mi pregunta es: ¿puedo unir dos formas diferentes como una forma? Por ejemplo, la esfera de unión y el cilindro juntos como uno?

¿Fue útil?

Solución

Algo así, sí, hay múltiples opciones:

  1. a través de la jerarquía simplemente puede agregar una malla a otra usando el add() función
  2. a través de geometryutil's merge() función para fusionar vértices y mallas de dos objetos de geometría en uno
  3. Uso de un editor 3D básico que admite operaciones booleanas entre mallas y exportación.

El método 1 es bastante sencillo:

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

Observe que 16 se repite, por lo que el nivel de las subdivisiones en una malla coincide con la otra (para un aspecto decente)

Método 2.1 - a través de geometrutils

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

Método 2.2 Fusionar un Espigas de torno y un cilindro:

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

El único problema que no puedo abordar en este momento proviene de las caras que están dentro de la malla. Idealmente, esos tendrían normales volteados para que no renderizaran, pero no han encontrado una solución rápida para eso.

El tercero es bastante sencillo. La mayoría de los paquetes 3D permiten la operación booleana en mallas (por ejemplo, fusionar dos mallas junto con la operación Agregar (Mesha + Meshb)). Intente crear un cilindro y una esfera en Licuadora(GRATIS, OpenSource), que ya tiene un tres.js exportador. Alternativamente, puede exportar un archivo .obj de las mallas fusionadas de su editor o elección 3D y usar el convert_obj_three guion.

Actualizar

He encontrado otro método, que podría ser más fácil/más intuitivo. ¿Recuerdas las operaciones booleanas que he mencionado anteriormente?

Resulta que hay una increíble biblioteca JS solo para eso: Geometría sólida constructiva:

CSG library preview from owner's github page

Chandler Prall escribió algunas funciones útiles para conectar CSG con tres.js. Entonces con la biblioteca CSG y el tres.js envoltura para ello, simplemente puedes hacer esto:

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

Que le da un buen resultado (sin problemas con caras adicionales/volteo normales/etc.):

cylinder-sphere union with CSG and three.js

Otros consejos

Actualicé Wrapper para tres.js R62, puedes encontrarlo aquí: https://github.com/kraag22/csg-wrapper

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top