Así que ahora tenemos un cubo, ¿pero qué pasa si queremos cambiar su posición o su tamaño? ¿O qué pasa si queremos uno o muchos cuboides rectangulares? Con nuestro código actual, tendríamos que cambiar los nodos uno por uno, lo cual sería molesto. Lo que nos gustaría es un método sencillo para crear un cuboide con una posición y dimensiones determinadas. En otras palabras, queremos una función que mapee una posición y dimensiones en un arreglo de nodos y un arreglo de aristas.

Definir un cuboide

Un cuboide tiene tres dimensiones: ancho, altura y profundidad:
También tiene una posición en el espacio 3D, lo que nos da seis parámetros. Hay un par de maneras en que podríamos definir la posición del cubo: podríamos definir su centro o podríamos definir una esquina. La primera es probablemente más común, pero creo que la última es más fácil de usar.
Nuestra función tiene que regresar un arreglo de nodos y uno de aristas. Una manera de regresar dos variables es empaquetando las variables en un objeto, con una clave para nodos y una clave para aristas. Ten en cuenta que puedes utilizar cualquier cadena de caracteres para referirte a la variable, pero a mí me parece más fácil usar la misma palabra.
// Crear un cuboide con un vértice en (x, y, z)
// con ancho w, altura h y profundidad d.
var createCuboid = function(x, y, z, w, h, d) {
   var nodes = [];
   var edges = [];
   var shape = { 'nodes': nodes, 'edges': edges };
   return shape;
};
Si usáramos esta función para crear un cuboide, accederíamos al primer nodo de esta manera:
var object = createCuboid(0, 0, 0, 100, 160, 50);
var node0 = shape.nodes[0];
Esto hará node0 igual al primer valor en el arreglo de nodos. Sin embargo, por el momento no existen valores en los arreglos de nodos o aristas.
Definimos los nodos como todas las combinaciones de posición con o sin la dimensión correspondiente. Las aristas se definen del mismo modo que antes (excepto que en lugar de definir primero cada una de las aristas individualmente, las defino todas a la vez). Observa que esta función te permite especificar dimensiones negativas para el cuboide.
var createCuboid = function(x, y, z, w, h, d) {
   var nodes = [[x, y, z ], [x, y, z+d], [x, y+h, z ], [x, y+h, z+d], [x+w, y, z ], [x+w, y, z+d], [x+w, y+h, z ], [x+w, y+h, z+d]];

   var edges = [[0, 1], [1, 3], [3, 2], [2, 0], [4, 5], [5, 7], [7, 6], [6, 4], [0, 4], [1, 5], [2, 6], [3, 7]];

   return { 'nodes': nodes, 'edges': edges};
};
Entonces podemos crear un cuboide con ancho 100, altura 160, profundidad 50 y un nodo en el origen así:
var shape = createCuboid(0, 0, 0, 100, 160, 50);
Como nuestro código anterior solo hace referencia a variables de nodos y aristas globales, tenemos que guardar las propiedades de nuestro objeto en esas globales:
var nodes = shape.nodes; var edges = shape.edges;
Puedes ver el código completo a continuación.

Trabajar con múltiples figuras

Podemos crear figuras con diferentes dimensiones, ¿qué pasa si queremos más de una? Siempre que queramos un número variable de cosas, un arreglo es útil, así que vamos a crear un arreglo de figuras.
var shape1 = createCuboid(-120, -20, -20, 240, 40, 40);
var shape2 = createCuboid(-120, -50, -30, -20, 100, 60);
var shape3 = createCuboid( 120, -50, -30, 20, 100, 60);
var shapes = [shape1, shape2, shape3];
Ahora tenemos que cambiar las funciones de despliegue y de rotación para que funcionen con un arreglo de objetos. Empieza por encerrar el código para desplegar las aristas en un bucle for que itere sobre todas las figuras:
// Dibuja aristas
stroke(edgeColor);
for (var shapeNum = 0; shapeNum < shapes.length; shapeNum++) {
   var nodes = shapes[shapeNum].nodes;
   var edges = shapes[shapeNum].edges;
   for (var e = 0; e < edges.length; e++) {
      var n0 = edges[e][0];
      var n1 = edges[e][1];
      var node0 = nodes[n0];
      var node1 = nodes[n1];
      line(node0[0], node0[1], node1[0], node1[1]);
   }
}
Y un bucle for similar para desplegar los nodos:
// Dibuja nodos
fill(nodeColor);
noStroke();
for (var shapeNum = 0; shapeNum < shapes.length; shapeNum++) {
   var nodes = shapes[shapeNum].nodes;
   for (var n = 0; n < nodes.length; n++) {
      var node = nodes[n]; ellipse(node[0], node[1], nodeSize, nodeSize);
   }
}
Podríamos añadir un bucle for similar para cada una de las funciones de rotación, pero creo que es más flexible pasarle el arreglo de nodos a cada función. De esa manera podemos rotar las figuras independientemente una de otra. Por ejemplo, la función rotateZ3D() se vería así:
var rotateZ3D = function(theta, nodes) { ... };
Ahora cuando usemos el ratón para rotar, tenemos que hacer un bucle sobre las figuras y llamar a la función para cada una:
mouseDragged = function() {
   var dx = mouseX - pmouseX;
   var dy = mouseY - pmouseY;
   for (var shapeNum = 0; shapeNum < shapes.length; shapeNum++) {
      var nodes = shapes[shapeNum].nodes;
      rotateY3D(dx, nodes);
      rotateX3D(dy, nodes);
   }
};
Asegúrate de eliminar cualquier otra llamada a las funciones de rotación que no pasen ningún nodo. Puedes ver el código completo a continuación.
Cargando