Cómo crear un motor 3D HTML5

 

Cómo crear su propio motor 3D HTML5

Probablemente ya sepa que HTML5 está cambiando las reglas del juego. En particular, con el lienzo HTML5, ha habido una avalancha de motores HTML5 3D JavaScript como three.js lanzados para mejorar la rudimentaria API 2D HTML5. Después de todo, los gráficos 3D son mucho más geniales que los gráficos 2D, ¿verdad?

Probablemente sea justo decir que si tuviera que crear un motor 3D completo, completo con transformaciones matriciales tridimensionales, objetos puntuales, objetos planos, sombreado, trazado de rayos y otros cálculos espaciales, sería bastante difícil.

Pero, ¿qué pasaría si quisiéramos crear un motor JavaScript 3D básico y optimizado que admita traducciones y rotaciones? ¿Qué tan difícil sería?

¿Qué pasa si te digo que podemos crear nuestro propio motor JavaScript 3D simple con solo 40 líneas de código?

Esta guía proporcionará un motor JavaScript simple y directo que habilita representaciones 3D HTML5 que se pueden usar en animaciones web, juegos, etc.

Comprensión de las proyecciones 3D

Antes de crear nuestro propio motor 3D, primero debemos entender cómo se crea la ilusión del espacio 3D en una pantalla 2D. Estas ilusiones se llaman Proyecciones 3D. Las proyecciones 3D mapean puntos en un plano bidimensional. En nuestro caso, los puntos tridimensionales definen un objeto que deseamos renderizar y el plano bidimensional es la pantalla de la computadora.

Como puede ver en la siguiente imagen, podemos crear una proyección tridimensional de un cubo en un plano bidimensional dibujando tres cuadriláteros irregulares: los cuadriláteros superior, izquierdo y frontal.

Proyecciones 3D

Proyecciones de plano con elipses

Desafortunadamente, calcular proyecciones tridimensionales puede ser bastante complejo de codificar. ¿Cómo podemos simplificarlo?

Imagínese mirando hacia abajo a un plano rectangular giratorio. Sus cuatro esquinas se encontrarían en el contorno de un círculo perfecto, cuyo radio es igual a la mitad de la distancia desde las esquinas opuestas del rectángulo.

Ahora imagina si tuviéramos que inclinar el avión en el espacio 3D. ¿Lo que pasa? Este círculo imaginario se convierte de repente en una elipse, cuya altura es menor que su ancho.

Esto significa que podríamos crear una proyección 3D simple creando planos cuyas esquinas residen a lo largo de los bordes de una elipse.

Si estamos definiendo la rotación del plano con un ángulo, theta, ¡los cálculos de proyección 3D de repente se vuelven bastante simples!

Cualquier punto en nuestro plano tridimensional se puede definir con las siguientes dos ecuaciones que describen un punto a lo largo de los bordes de una elipse:

x = A * cos(theta)
y = B * sin(theta)

dónde A es la mitad del ancho de la elipse, y B es la mitad de la altura de la elipse.

Un motor 3D simple

Si nuestro motor simplemente crea planos en el espacio 3D, podemos construir múltiples planos transversales que enmarcan un objeto 3D que deseamos renderizar.

Ejemplo de renderizado de objetos 3D

Proyecciones de plano con elipses

Diagrama de planos transversales

Proyecciones de plano con elipses

Ver demo

Esta forma 3D particular se creó generando tres planos de sección transversal: el plano superior, central e inferior. Estos planos imaginarios nos proporcionan todos los puntos que necesitamos para renderizar el objeto 3D usando la API de HTML5 Canvas.

Al crear una función sencilla que puede generar, trasladar y rotar estos planos transversales, hemos creado efectivamente un motor 3D simple.

Aquí está el código para nuestro motor 3D HTML5:

// This simple 3D engine was provided by www.Html5CanvasTutorials.com
// for the purpose of creating 3D HTML5 renderings
function Plane(centerX,centerY, planeLength, planeWidth, planeTilt, planeTheta) {
   this.centerX = centerX;
   this.centerY = centerY;
   this.planeLength = planeLength;
   this.planeTheta = planeTheta;
   
   var lastPerspectiveX = null;
   var lastPerspectiveX2 = null;
   var planeNextCornerAngle = 2*Math.asin(planeWidth/planeLength);
   
   this.rotate = function(newTheta) {
   	planeTheta = newTheta - planeNextCornerAngle/2;
   }
   
   this.translate = function(newCenterX, newCenterY) {
   	centerX = newCenterX;
   	centerY = newCenterY;
   }
   
   this.generate = function() {
   	var ovalLength = planeLength;
   	var ovalWidth = ovalLength * planeTilt;
   
   	var perspectiveX = (ovalLength / 2) * Math.cos(planeTheta);
   	var perspectiveY = (ovalWidth / 2) * Math.sin(planeTheta);             
   	var perspectiveX2 = (ovalLength / 2) * Math.cos(planeTheta + planeNextCornerAngle);
   	var perspectiveY2 = (ovalWidth / 2) * Math.sin(planeTheta + planeNextCornerAngle);
   
   	this.topLeftX = (perspectiveX *1) + centerX;
   	this.topLeftY = (perspectiveY * -1) + centerY;
  	this.bottomRightX = (perspectiveX*-1) + centerX;
   	this.bottomRightY = (perspectiveY*1) + centerY
   	this.topRightX = (perspectiveX2 *1) + centerX;
  	this.topRightY = (perspectiveY2 *-1) + centerY;
   	this.bottomLeftX = (perspectiveX2 *-1) + centerX;
   	this.bottomLeftY = (perspectiveY2 *1) + centerY;
   }
 }

Este sencillo motor 3D es completamente gratuito de usar y modificar siempre que mantenga los créditos comentados en su código. ¡Disfrutar!

Deja un comentario