I was born in 1981 in one little city. Since I was 10y/o I programmed in different languages. My first languages were basic, then C++/MFC, after .Net (C#, VB.Net, J#, ASP.Net), XSL+XML processing). In the last 5 years I worked with web languages (HTML, CSS, PHP, SQL, XML, XSL, JavaScript). After university I worked in several different companies, eventually becoming a blogger. This is my hobby too. Andrey is a DZone MVB and is not an employee of DZone and has posted 110 posts at DZone. You can read more from them at their website. View Full User Profile

WebGL With Three.js - Lesson 6

07.16.2014
| 3578 views |
  • submit to reddit

Today we continue our WebGL lessons for those who study it and want to enhance their knowledge. In today’s lesson we will look at the load process of ready three-dimensional objects. There are many websites where you can download these models, and moreover, if you have an editor of three-dimensional objects (like 3D Max, Maya, or even Blender), you can create your own models. There are also many file formats of three-dimensional objects, such as obj, collada (dae), obj, mtl, stl, vrml and so on. Most of them can be loaded into your three.js scenes using special loaders. And today we will consider how to load three-dimensional models using a variety of loaders.

Live Demo 1
Live Demo 2
Live Demo 3
Live Demo 4

OBJ

In order to load object files (.obj), we can use OBJLoader.js. It is rather easy to use this library, but before all, we need to attach the library (in the section where we link all other necessary scripts):

<script src="js/three.min.js"></script>
<script src="js/OBJLoader.js"></script>
<script src="js/THREEx.WindowResize.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/script1.js"></script>

Now, let’s prepare a general skeleton (of all our demos):

var lesson6 = {
  scene: null,
  camera: null,
  renderer: null,
  container: null,
  controls: null,
  clock: null,
  stats: null,

  init: function() { // Initialization

    // create main scene
    this.scene = new THREE.Scene();
    this.scene.fog = new THREE.FogExp2(0xcce0ff, 0.0003);

    var SCREEN_WIDTH = window.innerWidth,
        SCREEN_HEIGHT = window.innerHeight;

    // prepare camera
    var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 1, FAR = 2000;
    this.camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
    this.scene.add(this.camera);
    this.camera.position.set(0, 100, 300);
    this.camera.lookAt(new THREE.Vector3(0,0,0));

    // prepare renderer
    this.renderer = new THREE.WebGLRenderer({ antialias:true });
    this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    this.renderer.setClearColor(this.scene.fog.color);
    this.renderer.shadowMapEnabled = true;
    this.renderer.shadowMapSoft = true;

    // prepare container
    this.container = document.createElement('div');
    document.body.appendChild(this.container);
    this.container.appendChild(this.renderer.domElement);

    // events
    THREEx.WindowResize(this.renderer, this.camera);

    // prepare controls (OrbitControls)
    this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
    this.controls.target = new THREE.Vector3(0, 0, 0);
    this.controls.maxDistance = 2000;

    // prepare clock
    this.clock = new THREE.Clock();

    // prepare stats
    this.stats = new Stats();
    this.stats.domElement.style.position = 'absolute';
    this.stats.domElement.style.left = '50px';
    this.stats.domElement.style.bottom = '50px';
    this.stats.domElement.style.zIndex = 1;
    this.container.appendChild( this.stats.domElement );

    // add spot light
    var spLight = new THREE.SpotLight(0xffffff, 1.75, 2000, Math.PI / 3);
    spLight.castShadow = true;
    spLight.position.set(-100, 300, -50);
    this.scene.add(spLight);

    // add simple ground
    var ground = new THREE.Mesh( new THREE.PlaneGeometry(200, 200, 10, 10), new THREE.MeshLambertMaterial({color:0x999999}) );
    ground.receiveShadow = true;
    ground.position.set(0, 0, 0);
    ground.rotation.x = -Math.PI / 2;
    this.scene.add(ground);

    // load a model
    this.loadModel();
  },
  loadModel: function() {

    ......
  }
};

// Animate the scene
function animate() {
  requestAnimationFrame(animate);
  render();
  update();
}

// Update controls and stats
function update() {
  lesson6.controls.update(lesson6.clock.getDelta());
  lesson6.stats.update();
}

// Render the scene
function render() {
  if (lesson6.renderer) {
    lesson6.renderer.render(lesson6.scene, lesson6.camera);
  }
}

// Initialize lesson on page load
function initializeLesson() {
  lesson6.init();
  animate();
}

if (window.addEventListener)
  window.addEventListener('load', initializeLesson, false);
else if (window.attachEvent)
  window.attachEvent('onload', initializeLesson);
else window.onload = initializeLesson;

This code creates the empty scene with camera, rendererm control stats and light. Please pay attention to the empty ‘loadModel’ function – we will put here different codes to load models of different formats. Our first format is ‘obj’. Have a look to the following implementation:

// prepare loader and load the model
var oLoader = new THREE.OBJLoader();
oLoader.load('models/chair.obj', function(object, materials) {

  // var material = new THREE.MeshFaceMaterial(materials);
  var material2 = new THREE.MeshLambertMaterial({ color: 0xa65e00 });

  object.traverse( function(child) {
    if (child instanceof THREE.Mesh) {

      // apply custom material
      child.material = material2;

      // enable casting shadows
      child.castShadow = true;
      child.receiveShadow = true;
    }
  });
  
  object.position.x = 0;
  object.position.y = 0;
  object.position.z = 0;
  object.scale.set(1, 1, 1);
  lesson6.scene.add(object);
});

Firstly, we created a new instance of THREE.OBJLoader, and then – we load the ‘chair.obj’ model file. In order to apply a custom material, we traversed through it’s children and applied the prepared material2 (THREE.MeshLambertMaterial). We also applied casting and receiving shadows. In the end – we set the position of the object and set the scale value.

MTL

In short, this is an addition for the previously described OBJ format. Because MTL is a file that describes materials of OBJ file. To load OBJ files with support of MTL, we can use another loader: OBJMTLLoader. In order to use it, don’t forget to include necessary libraries:

<script src="js/MTLLoader.js"></script>
<script src="js/OBJMTLLoader.js"></script>

Now add the following code into our ‘loadModel’ function:

// prepare loader and load the model
var oLoader = new THREE.OBJMTLLoader();
oLoader.load('models/castle.obj', 'models/castle.mtl', function(object) {

  object.position.x = -200;
  object.position.y = 0;
  object.position.z = 100;
  object.scale.set(0.1, 0.1, 0.1);
  lesson6.scene.add(object);
});

As you can see, the load function accepts more params – we can point our ‘mtl’ file with materials. This method allows us to load model (obj) with textures!

DAE

Collada files (dae) are also popular among 3d designers. This format supports textures as well. In order to load this format, we can use another loader: ColladaLoader. To use it, don’t forget to include necessary libraries:

<script src="js/ColladaLoader.js"></script>

Now add the following code into our ‘loadModel’ function:

// prepare loader and load the model
var oLoader = new THREE.ColladaLoader();
oLoader.load('models/mlc.dae', function(collada) {

  var object = collada.scene;
  var skin = collada.skins[0];

  object.rotation.x = -Math.PI / 2;
  object.rotation.z = Math.PI / 2;
  object.position.x = -50;
  object.position.y = -100;
  object.position.z = 0;
  object.scale.set(0.025, 0.025, 0.025);
  object.updateMatrix();
  lesson6.scene.add(object);
});

JSON

This format is natively supported by three.js. It also support custom materials (with textures) that are described in the json file. In order to load this format, we can use another loader: JSONLoader:

// prepare loader and load the model
var oLoader = new THREE.JSONLoader();
oLoader.load('models/palm.js', function(geometry, materials) {

  // get original materials
  var material = new THREE.MeshFaceMaterial(materials);

  var mesh = new THREE.Mesh(geometry, material);

  mesh.position.x = -50;
  mesh.position.y = -80;
  mesh.position.z = 0;
  mesh.scale.set(10, 10, 10);
  lesson6.scene.add(mesh);
});
Live Demo 1
Live Demo 2
Live Demo 3
Live Demo 4

 


Published at DZone with permission of Andrey Prikaznov, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)