Today we continue our lessons for those who study webgl, and today we will show you how to add 3D text on the scene, how to extrude two-dimensional shapes, we also will consider how to load ready 3D models into the scene using the OBJLoader. It seems to be a difficult process, but it is not – the code for loading 3D models is fairly simple.
HTML
Two new libraries were added into the html: font1.js and OBJLoader.js
04 | <meta charset="utf-8" /> |
05 | <meta name="author" content="Script Tutorials" /> |
06 | <title>WebGL With Three.js - Lesson 4 | Script Tutorials</title> |
07 | <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
08 | <link href="css/main.css" rel="stylesheet" type="text/css" /> |
11 | <script src="js/three.min.js"></script> |
12 | <script src="js/THREEx.WindowResize.js"></script> |
13 | <script src="js/OrbitControls.js"></script> |
14 | <script src="js/fonts/font1.js"></script> |
15 | <script src="js/OBJLoader.js"></script> |
16 | <script src="js/stats.min.js"></script> |
17 | <script src="js/script.js"></script> |
Javascript
First, we create a simple (empty) scene (scene, camera, renderer, controls, light and ground):
02 | var texture = THREE.ImageUtils.loadTexture('texture.png'); |
03 | texture.repeat.set(0.03, 0.03); |
04 | texture.wrapS = texture.wrapT = THREE.RepeatWrapping; |
05 | texture.anisotropy = 16; |
06 | texture.needsUpdate = true; |
17 | this.scene = new THREE.Scene(); |
18 | var SCREEN_WIDTH = window.innerWidth, |
19 | SCREEN_HEIGHT = window.innerHeight; |
21 | var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 1, FAR = 10000; |
22 | this.camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR); |
23 | this.scene.add(this.camera); |
24 | this.camera.position.set(0, 400, 800); |
25 | this.camera.lookAt(new THREE.Vector3(0,0,0)); |
27 | this.renderer = new THREE.WebGLRenderer({antialias:true, alpha: false}); |
28 | this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); |
29 | this.renderer.setClearColor(0xffffff); |
30 | this.renderer.shadowMapEnabled = true; |
31 | this.renderer.shadowMapSoft = true; |
33 | this.container = document.createElement('div'); |
34 | document.body.appendChild(this.container); |
35 | this.container.appendChild(this.renderer.domElement); |
37 | THREEx.WindowResize(this.renderer, this.camera); |
39 | this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement); |
40 | this.controls.target = new THREE.Vector3(0, 0, 0); |
42 | this.clock = new THREE.Clock(); |
44 | this.stats = new Stats(); |
45 | this.stats.domElement.style.position = 'absolute'; |
46 | this.stats.domElement.style.bottom = '0px'; |
47 | this.stats.domElement.style.zIndex = 10; |
48 | this.container.appendChild( this.stats.domElement ); |
50 | var dLight = new THREE.DirectionalLight(0xffffff); |
51 | dLight.position.set(0, 1000, 0); |
52 | dLight.castShadow = true; |
54 | this.scene.add(dLight); |
56 | var groundGeometry = new THREE.PlaneGeometry(1000, 1000, 1, 1); |
57 | ground = new THREE.Mesh(groundGeometry, new THREE.MeshLambertMaterial({ |
58 | color: 0x4489FE, side: THREE.DoubleSide |
60 | ground.position.y = -20; |
61 | ground.rotation.x = - Math.PI / 2; |
62 | ground.receiveShadow = true; |
63 | this.scene.add(ground); |
68 | requestAnimationFrame(animate); |
74 | lesson4.controls.update(lesson4.clock.getDelta()); |
75 | lesson4.stats.update(); |
79 | if (lesson4.renderer) { |
80 | lesson4.renderer.render(lesson4.scene, lesson4.camera); |
84 | function initializeLesson() { |
88 | if (window.addEventListener) |
89 | window.addEventListener('load', initializeLesson, false); |
90 | else if (window.attachEvent) |
91 | window.attachEvent('onload', initializeLesson); |
92 | else window.onload = initializeLesson; |
3D text
The best way to display text in 3D enviromnemt is to use a ready 3D font (for Three.js). In general, there are many websites where you can download fonts, however we need special javascript fonts (typefaced fonts). This website may help you to convert custom fonts into javascript fonts (upload your font, hit the ‘convert’, and then follow the steps until it let you download the result). However, at the time of writing this tutorial, this service was not available, so I had to use ready-made fonts to create our demonstration. To draw a three-dimensional text I prepared the following function:
01 | draw3dText: function(x, y, z, text) { |
03 | var textGeometry = new THREE.TextGeometry(text, { |
17 | var materialFront = new THREE.MeshPhongMaterial({ map: texture, color: 0xffff00, emissive: 0x888888 }); |
18 | var materialSide = new THREE.MeshPhongMaterial({ map: texture, color: 0xff00ff, emissive: 0x444444 }); |
20 | var textMaterial = new THREE.MeshFaceMaterial([ materialFront, materialSide ]); |
21 | var textMesh = new THREE.Mesh(textGeometry, textMaterial); |
22 | textMesh.castShadow = true; |
24 | textMesh.position.set(x, y, z); |
25 | textMesh.rotation.x = -0.3; |
26 | this.scene.add(textMesh); |
Two different materials are used to different sides of the text (for the front and side).
ExtrudeGeometry
This class allows us to create three-dimensional extruded geometry from two-dimensional path shape. I drew the boat for our today’s demonstration:
01 | drawCustomObject: function(x, y, z) { |
04 | new THREE.Vector2 (275, 265), |
05 | new THREE.Vector2 (205, 240), |
06 | new THREE.Vector2 (125, 220), |
07 | new THREE.Vector2 (274, 115), |
08 | new THREE.Vector2 (275, 85), |
09 | new THREE.Vector2 (330, 85), |
10 | new THREE.Vector2 (310, 100), |
11 | new THREE.Vector2 (330, 115), |
12 | new THREE.Vector2 (275, 115), |
13 | new THREE.Vector2 (274, 266), |
14 | new THREE.Vector2 (305, 266), |
15 | new THREE.Vector2 (305, 240), |
16 | new THREE.Vector2 (360, 240), |
17 | new THREE.Vector2 (360, 285), |
18 | new THREE.Vector2 (340, 335), |
19 | new THREE.Vector2 (215, 335), |
20 | new THREE.Vector2 (175, 320), |
21 | new THREE.Vector2 (150, 290), |
22 | new THREE.Vector2 (75, 230), |
23 | new THREE.Vector2 (200, 264), |
24 | new THREE.Vector2 (274, 264), |
27 | var objectShape = new THREE.Shape(objectPoints); |
28 | var extrusionSettings = { |
38 | var objectGeometry = new THREE.ExtrudeGeometry( objectShape, extrusionSettings ); |
40 | var materialFront = new THREE.MeshPhongMaterial({ map: texture, color: 0xffff00, emissive: 0x888888 }); |
41 | var materialSide = new THREE.MeshPhongMaterial({ map: texture, color: 0xff00ff, emissive: 0x444444 }); |
43 | var objectMaterial = new THREE.MeshFaceMaterial([ materialFront, materialSide ]); |
44 | var objectMesh = new THREE.Mesh( objectGeometry, objectMaterial ); |
45 | objectMesh.castShadow = true; |
47 | objectMesh.position.set(x, y, z); |
48 | objectMesh.rotation.x = Math.PI; |
49 | this.scene.add(objectMesh); |
OBJLoader
I left the most interesting for the end – loading ready OBJ models. The fact that there are a huge number of ready three-dimensional objects (at various websites) that you can add into your scene, and three.js gives us this opportunity through the use of the OBJLoader class:
01 | loadObjFile: function(x, y, z) { |
03 | var loader = new THREE.OBJLoader(); |
04 | loader.load('legoBrick.obj', function(object) { |
06 | var legoMat = new THREE.MeshLambertMaterial({ color: 0x008800 }); |
07 | object.traverse( function (child) { |
08 | if (child instanceof THREE.Mesh) { |
09 | child.material = legoMat; |
10 | child.material.needsUpdate = true; |
14 | object.position.x = x; |
15 | object.position.y = y; |
16 | object.position.z = z; |
17 | object.rotation.y = Math.PI/2; |
18 | object.scale.set(40, 40, 40); |
19 | lesson4.scene.add(object); |
To import the model we just specify the address to this model, as well as the callback function. In this function we applied the custom material for it’s children.
[sociallocker]
[/sociallocker]
Conclusion
Stay tuned for new lessons and you are sure to find something new and interesting for yourself.