2011-11-30 33 views

Respuesta

40

una especie de, sí, hay varias opciones:

  1. a través de la jerarquía Usted puede simplemente añadir una malla a otra usando la función
  2. add() través de la función de GeometryUtil merge() fusionar vértices y mallas de dos objetos de geometría en uno
  3. usando un editor 3D básico que admita operaciones Booleanas entre mallas y exportación.

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

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

Método 2.1 - a través 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); 

Método 2.2 fusión de un Lathe half-sphere 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 resolver en este momento proviene de las caras que están dentro de la malla. Idealmente, aquellos tendrían las normales volteadas para que no se rendericen, pero no hayan encontrado una solución rápida para eso.

El tercero es bastante directo. La mayoría de los paquetes 3D permiten la operación booleana en mallas (por ejemplo, fusionar dos mallas junto con la operación ADD (meshA + meshB)). Intente crear un cilindro y una esfera en Blender (libre, código abierto), que ya tiene un exportador three.js. Alternativamente, puede exportar un archivo .obj de las mallas fusionadas desde su editor o elección en 3D y usar el script convert_obj_three.

actualización

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

resulta que hay una biblioteca de JS increíble sólo por eso: Constructive Solid Geometry:

CSG library preview from owner's github page

Chandler Prall escribió algunas funciones útiles para conectar CSG with three.js. Así que con la biblioteca de CSG y la three.js wrapper for it, puede simplemente 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 (no hay problemas con las caras supletorias/normales voltear/etc.):

cylinder-sphere union with CSG and three.js

+0

Estoy intentando todas esas cosas, gracias por las respuestas! Hice esta pregunta ya que estoy tratando de crear flores en 3D con varias formas y texturas. Mi propósito es unir las formas, así puedo rotar y arrastrar todas las formas de flores y no todas las formas juntas como una sola forma – BorisD

+0

Suena un poco como [Hello Enjoy's HelloFlower app] (http://helloenjoy.com/helloflower/). En este caso, diría que tiene un Object3D "contenedor" vacío en la parte superior, y luego 'agregar()' los pétalos, pistilo, etc. a eso para que pueda manipular el grupo. Algo así como la primera sugerencia, pero en lugar de agregar directamente a la escena, agregar a un contenedor ('scene.add (contenedor); container.add (flowerPartA); container.add (flowerPartB); // etc.') –

+0

Wow ! es un gran ejemplo ... no es exactamente lo que intento construir, pero hay algunas cosas similares. Durante los últimos días tuve un buen progreso. Espero que mi último ejemplo que publique, ayude al principiante en Three.js a resolver algunos problemas pequeños y más grandes. Pero aún hay algunas cosas pequeñas con las que aún no estoy familiarizado ... ¿Cómo puedo crear algo así como la forma del cilindro que comienza en el punto X y termina en un punto Y ... por ahora lo único que puedo descubrir es solo hacer un cilindro y rotarlo? – BorisD

Cuestiones relacionadas