使用Three.js + Blender构建在浏览器端显示的3D模型(4)

时间:2024-03-01 18:04:04

 第四章 使用three.js加载以图片为纹理的模型(上)

在前言中我们介绍过,我们一般不用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程序了。