在前言中我们介绍过,我们一般不用three.js自带的三维模型创建函数去拼凑我们想要的三维模型,而是使用类似Blender一样的三维建模工具去定制三维模型,然后导出为three.js可以识别的jason格式,加载显示。通过这种方式,我们可以构建较为原始的三维模型在浏览器端显示,比如我们前面看到的马克杯模型。如果单纯依靠三维建模去逼近现实世界中的形体外观是很难的,细节的修缮将给3D建模带来巨大的工作量,同时也会导致模型的加载器计算量巨大,不仅对人还是机器都是巨大的挑战。
好在我们可以另辟蹊径,不去追求模型的精细度,而在模型的纹理上做文章,尤其当我们用真实物体的照片作为模型纹理的时候,3D模型的效果立刻就得到了极大的提高,比如这个箱体模型:
如果不考虑外表图片纹理,它只是一个简单的立方体模型。加上纹理之后,几乎和我们在一些制作精良的3D游戏中见到的箱体所差无几了。下面我们来分析它的代码:
1 //兼容各种浏览器的animation函数
2 window.requestAnimFrame = (function(callback){
3 return window.requestAnimationFrame ||
4 window.webkitRequestAnimationFrame ||
5 window.mozRequestAnimationFrame ||
6 window.oRequestAnimationFrame ||
7 window.msRequestAnimationFrame ||
8 function(callback){
9 window.setTimeout(callback, 1000 / 60);
10 };
11 })();
12
13 // 实现旋转的动画函数
14 function animate(lastTime, angularSpeed, three){
15 // 动画更新时以时间为基准
16 var date = new Date();
17 var time = date.getTime();
18 var timeDiff = time - lastTime;
19 // 角度以弧度为单位
20 var angleChange = angularSpeed * timeDiff * 2 * Math.PI / 1000;
21 three.cube.rotation.y += angleChange;
22 lastTime = time;
23
24 // 重新渲染
25 three.renderer.render(three.scene, three.camera);
26
27 // 角度参数在第一次调用时设定
28 requestAnimFrame(function(){
29 animate(lastTime, angularSpeed, three);
30 });
31 }
32
33 window.onload = function(){
34 var angularSpeed = 0.2;
35 var lastTime = 0;
36
37 // 渲染器
38 var renderer = new THREE.WebGLRenderer();
39 renderer.setSize(window.innerWidth, window.innerHeight);
40 document.body.appendChild(renderer.domElement);
41
42 // 摄像机
43 var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
44 camera.position.z = 700;
45
46 // 场景
47 var scene = new THREE.Scene();
48
49 // 以图片为纹理的材质,这是关键点
50 var material = new THREE.MeshLambertMaterial({
51 map: THREE.ImageUtils.loadTexture("crate.jpg")
52 });
53
54 // 立方体模型
55 var cube = new THREE.Mesh(new THREE.CubeGeometry(300, 300, 300), material);
56 cube.overdraw = true;
57 scene.add(cube);
58
59 // 加入环境光
60 var ambientLight = new THREE.AmbientLight(0x555555);
61 scene.add(ambientLight);
62
63 // 加入方向光
64 var directionalLight = new THREE.DirectionalLight(0xffffff);
65 directionalLight.position.set(1, 1, 1).normalize();
66 scene.add(directionalLight);
67
68 // 把以上创建3D模型的要素都包装成一个对象
69 var three = {
70 renderer: renderer,
71 camera: camera,
72 scene: scene,
73 cube: cube
74 };
75
76 // 使用onload回调函数启动动画,这样能保证图片被完全加载后才开始旋转
77 var textureImg = new Image();
78 textureImg.onload = function(){
79 animate(lastTime, angularSpeed, three, this);
80 };
81 textureImg.src = "crate.jpg";
82 };
与之对应的html代码如下:
1 <!DOCTYPE HTML>
2 <html lang="en">
3 <head>
4 <style>
5 body {
6 margin: 0px;
7 overflow: hidden;
8 }
9 </style>
10 </head>
11 <body>
12 <script src="http://mrdoob.github.com/three.js/build/three.min.js"></script>
13 <script src="LoadCrate.js"></script>
14 </body>
15 </html>
这个纹理图片可以在这里下载:http://www.html5canvastutorials.com/demos/webgl/html5_canvas_webgl_texture/crate.jpg
这篇文章也参考自:http://www.html5canvastutorials.com/webgl/html5-canvas-webgl-texture-with-three-js/
作为一个系列中的一篇,相信这篇文章能够让初学者有效的向前推进一步,迈向three.js自由应用的大门!
在下一篇里,我们将分析如何给一个用Blender制作的,较为复杂的模型贴图显示在浏览器端。
另外,实践中我们发现,可以使用Chrome浏览器加载本地的WebGL模型中的素材,只需要在启动Chrome的时候加上一下参数:--allow-file-access-from-files --disable-web-security
或许只加--allow-file-access-from-files就足够了。方法如下图所示:
这样以来我们就可以随意选择自己偏爱的浏览器去调试three.js程序了。