Inicio | Apuntes breves | Publicación 3D via web con Three.js

Publicación 3D via web con Three.js

Domingo, 25 de Mayo de 2014 19:15

three.jsHace ya algún tiempo abordaba la problemática de la publicación y distribución de contenidos 3D ya que con frecuencia una buena parte de la documentación 3D generada, raras veces acaba viendo la luz por lo poco usual de las herramientas de visualización de contenidos 3D, el peso de muchos de los documentos y lo relativamente ajeno de ciertas estrategias de publicación web.
Aunque en los últimos años plataformas propietarias como Sketchfab o p3dj.in se han convertido en una interesante solución, los costes que su uso implica a largo plazo puede no ser especialmente sostenible para ciertos proyectos.

Como alternativa, tenemos el conocido el 3D PDF o el X3DOM para web, basado en el formato X3D, el cual se presenta como una fuerte apuesta para la estandarización en la publicación web.

El problema de la publicación en X3DOM es, por ahora, la dependencia de herramientas como AOPT de Instant Player, para realizar las conversiones a partir de documentos X3D a HTML5

Actualmente quizás una de las pocas alternativas maduras a X3DOM podría ser el proyecto Three.js, que como su nombre indica esta basado en Javascript y aprovecha igualmente las capacidades webGL de nuestros exploradores para renderizar modelos 3D a traves de la Web.

Quizás una de las posibilidades más interesantes de Three.js, frente al uso de X3DOM, es el uso directo de formatos de archivo como Wavefront (.obj) o Stanford Triangle Format (.ply) unos formato de archivo tremendamente comunes, por lo que no es necesario ninguna preparación previa del modelo, salvo, la evidente y necesaria simplificación del modelo, con el fin de reducir el tamaño de nuestros documentos lo suficiente, para su carga vía web sin aburrir al usuario en tiempos de espera eternos.

Three.js es un proyecto open-source liberado por Ricardo Cabello en 2010, casualmente en el mismo año que surge X3DOM. En la actualidad dicho proyecto posee un fuerte desarrollo y ha sido escalado con un buen número de librerías que aportan interesantes funcionalidades.

Nos podemos hacer una idea de las tremendas posibilidades de dicha librería a través de la web del Museo de Paleontología de la universidad de Michigan (http://umorf.ummp.lsa.umich.edu/wp/ )

Introducción al uso de Three.js

Podemos introducirnos fácilmente en el uso de dicha librería gracias a los numerosos ejemplos que podemos descargar de su web ( http://mrdoob.github.io/three.js/examples/ ). El siguiente código que vamos a ver, esta tomado del ejemplo de carga de documentos en formato Wavefront (obj Loader).

En este ejemplo se usan cuatro librerías:

  • Three.js que es la librería principal encargada de generar el render de nuestro modelo vía webGL
  • TrackballControls.js la cual como su nombre indica nos permite la rotación del modelo (control de cámaras)
  • OBJLoader.js, encargada de la carga de modelos en formato Wavefront (.obj)
  • Detector.js cuya misión es verificar si nuestro explorador de internet tiene soporte para webGL

El código fuente completo es el siguiente:

 <script src="/js/three.min.js"></script>
  <script src="/js/TrackballControls.js"></script>
  <script src="/js/OBJLoader.js"></script>
  <script src="/js/Detector.js"></script>
 <script>
 var container, stats;
  var camera, scene, renderer;
  var mouseX = 0, mouseY = 0;
  var windowHalfX = window.innerWidth / 2;
  var windowHalfY = window.innerHeight / 2;
 init();
  animate();
 function init() {
 container = document.createElement( 'div' );
  document.body.appendChild( container );
  camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
  camera.position.z = 100;
  controls = new THREE.TrackballControls( camera );
  controls.rotateSpeed = 5.0;
  controls.zoomSpeed = 5;
  controls.panSpeed = 2;
  controls.noZoom = false;
  controls.noPan = false;
  controls.staticMoving = true;
  controls.dynamicDampingFactor = 0.3;
 // escena
  scene = new THREE.Scene();
 // luz ambiente
  var ambient = new THREE.AmbientLight( 0xffffff );
  scene.add( ambient );
 // Carga textura
  var texture = new THREE.Texture();
  var loader = new THREE.ImageLoader();
  loader.addEventListener( 'load', function ( event ) {
  texture.image = event.content;
  texture.needsUpdate = true;
  texture.magFilter = THREE.NearestFilter;
  texture.minFilter = THREE.NearestMipMapLinearFilter;
  } );
  loader.load( 'diosa_textura_low.png' );
 // Carga modelo
 var loader = new THREE.OBJLoader();
  loader.addEventListener( 'load', function ( event ) {
 var object = event.content;
  object.traverse( function ( child ) {
  if ( child instanceof THREE.Mesh ) {
  child.material.map = texture;
  }
  } );
  object.scale = new THREE.Vector3(25,25,25 );
  scene.add( object );
  });
  loader.load( 'diosa.0.mesh_low_low.textura.obj' );
 // Renderiza con webGL
  renderer = new THREE.WebGLRenderer();
  renderer.setSize( window.innerWidth, window.innerHeight );
  container.appendChild( renderer.domElement );
  document.addEventListener( 'mousemove', onDocumentMouseMove, false );
  window.addEventListener( 'resize', onWindowResize, false );
 }
 function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
  }
 function onDocumentMouseMove( event ) {
  mouseX = ( event.clientX - windowHalfX ) / 2;
  mouseY = ( event.clientY - windowHalfY ) / 2;
  }
 function animate() {
  requestAnimationFrame( animate );
  render();
  }
 function render() {
  controls.update();
  camera.lookAt( scene.position );
  renderer.render( scene, camera );
  }
 </script>
  <div>
<canvas width="800" height="800" style="width: 800px; height: 800px;"></canvas>
</div>

De este código es interesante destacar la carga de nuestra textura en:

loader.load( 'diosa_textura_low.png' );

Y finalmente la carga del archivo Wavefront

loader.load( 'diosa.0.mesh_low_low.textura.obj' );

Hay que tener presente que OBJLoader también puede cargar documentos .mtl para la referencia de materiales.

loader.load( 'diosa.0.mesh_low_low.textura.obj', 'diosa.0.mesh_low_low.textura.mtl')

A continuación podeis ver un pequeño modelo de 24.000 polígonos, con un peso total de 1.4Mb y una textura jpeg de 500Kb publicado con Three.js: The Queen of The Night

x-rite Professional LED Lighting, DSLR Support and Accessories for Photo and Video BabelColor asociacion española de imagen cientifica y forense