Tutorial: un Solidify simple en Processing

Actualización (12/11/12): La versión anterior del código tenía un bug. Todos los enlaces de este tutorial apuntan a la versión actualizada del archivo, que podéis descargar directamente aquí.

La creación de objetos a través del código consiste en especificar mediante algoritmos las posiciones de los vértices del volumen. Estos vértices dibujan la superficie del objeto, no su relleno. Cuando la superficie que creamos es cerrada, programas de impresión 3D como ReplicatorG la interpretan como un sólido que hay que rellenar. El parámetro infill regula precisamente la densidad de este relleno: 30% para una pieza estándar, o 0% para una pieza cerrada pero hueca.
A veces sin embargo nos interesa crear superficies con aberturas, como un edificio con ventanas, por ejemplo. En estos casos estamos obligados a dotar a la superficie de un grosor, ya que estas, las superficies abiertas, son objetos que no interpretan correctamente los programas de impresión 3D.
El modelador open source Blender proporciona esta opción bajo el nombre Solidify. En este tutorial presentamos una versión muy sencilla de este solidify implementado en Processing con las fantásticas librerías Toxiclibs con el que podremos dotar a nuestras superficies, abiertas o no, de un revestimiento.

Para ello hemos creado una función que se encarga de generar automáticamente el revestimiento de una superficie cualquiera. En el ejemplo que vamos a mostrar trataremos un cubo con una de sus caras abiertas. La función, que es por el momento un primer prototipo de un auténtico solidify en Processing, calcula el revestimiento a partir de la superficie. Llamemos a esta «cuboAbierto».

WETriangleMesh interior = simpleSolidify(cuboAbierto, 10);

La función toma la superficie como argumento, junto a un valor de grosor en milímetros. simpleSolidify proporciona una superficie interior que podremos añadir a nuestro modelo. Veámoslo paso por paso.
Creamos la superficie inicial
Necesitamos en primer lugar crear una superficie inicial, que la del cubo abierto en nuestro ejemplo. Para crearla vamos a hacer uso de una clase propia, WEQuadStrip, que permite crear superficies a partir de vértices tal y como las crearíamos con beginShape(QUAD_STRIP) en Processing: como vías de tren especificadas por los extremos de los raíles. Podéis descargar esta clase en el zip del tutorial.
Con esta creamos el cubo abierto a partir de las coordenadas de los vértices:

// Generamos el objeto al que queremos darle grosor.
// En este caso un cubo abierto por una de sus caras.
cuboAbierto = new WETriangleMesh();
WEQuadStrip qs = new WEQuadStrip();
//
qs.beginShape();
qs.vertex(0, 0, 100);
qs.vertex(0, 100, 100);
qs.vertex(0, 0, 0);
qs.vertex(0, 100, 0);
qs.vertex(100, 0, 0);
qs.vertex(100, 100, 0);
qs.vertex(100, 0, 100);
qs.vertex(100, 100, 100);
qs.endShape();
//
qs.beginShape();
qs.vertex(0, 0, 100);
qs.vertex(100, 0, 100);
qs.vertex(0, 0, 0);
qs.vertex(100, 0, 0);
qs.endShape();
//
qs.beginShape();
qs.vertex(0, 100, 0);
qs.vertex(100, 100, 0);
qs.vertex(0, 100, 100);
qs.vertex(100, 100, 100);
qs.endShape();
//
// Añadimos la superficie creada al objeto total «cuboAbierto»
cuboAbierto.addMesh(qs);

Solidify
Antes de generar el revestimiento es necesario saber si va a crearse hacia afuera o hacia adentro del volumen. Esto es, si las paredes van a crecer hacia el exterior o al interior del volumen. Vamos a optar en este ejemplo por crearlo hacia adentro.
Para ello es necesario orientar las normales de las caras de nuestra superficie hacia dentro:

// Orientamos las normales de las caras de cuboAbierto hacia adentro si queremos que
// el «solidify» mantenga el volumen exterior total del objeto
cuboAbierto.faceOutwards();
cuboAbierto.flipVertexOrder(); // En caso de crecimientos hacia afuera, eliminamos esta línea

Con la superficie creada y con sus normales orientadas hacia el interior, podemos ya generar la pared que le dará grosor. Para ello tenemos que seguir tres pasos:
1. crear el revestimiento con la función simpleSolidify
2. reorientar hacia afuera las normales de nuestra superficie original
3. pegar el revestimiento a la superficie para que sumen un objeto único
Esto es lo que hacemos a continuación:

// Creamos el borde «solidify» de la superficie con la función
// simpleSolifidy( … ) que toma como argumento la superficie,
// en este caso, cuboAbierto
WETriangleMesh interior = simpleSolidify(cuboAbierto, 10);
//
// Volvemos a orientar hacia fuera las normales de cuboAbierto
// para no tener problemas en la impresión 3D del objeto
cuboAbierto.faceOutwards();
//
// Añadimos el revestimiento que acabamos de generar
// al objeto total
cuboAbierto.addMesh(interior);

¡No hace falta nada más! En esta imagen podéis ver el borde durante la impresión y el objeto final.

simpleSolidify: el código
Como es algo largo como para copiarlo directamente aquí, el código comentado de la función puede descargarse en el zip del tutorial. En esta sección vamos a comentar cómo funciona.
Antes de nada hay que tener en cuenta que la función resuelve dos problemas: el primero, crear una superficie de revestimiento a partir de una dada; el segundo, encontrar agujeros en la superficie y crear los bordes con los que cerrar el objeto final (el alféizar de la ventana, para entendernos). En este momento, y para este ejemplo, la función sólo nos permite resolver el problema para un agujero en la superficie.
El mecanismo de la función consiste en recorrer todas las caras (WEFaces) de la superficie inicial y encontrar dos cosas: las coordenadas de sus vértices y las caras vecinas a cada una de ellas. Los nuevos vértices de la superficie de revestimiento son calculados entonces como un desplazamiento de la posición de los originales igual a la suma de las normales de las caras vecinas. Con estos, cara a cara, la superficie de revestimiento va construyéndose bajo la original.
El segundo punto es encontrar los agujeros de la superficie y crear los alféizares. Para ello la función, en su recorrido vértice a vértice de la superficie inicial, detecta aquellas aristas que sólo cuentan con una cara. Sus vértices son recogidos en una lista, y posteriormente vinculados a los vértices de la nueva superficie de revestimiento. Como tenemos los dos extremos de los raíles, construir la vía es sencillo, de nuevo, con un WEQuadStrip.
Descargad el tutorial aquí y no dudéis en añadir un comentario a este post si os encontráis con algún problema.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *