您的位置:首页 > Web前端 > JavaScript

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

2015-09-28 15:45 756 查看
http://www.cnblogs.com/rsail/archive/2012/10/16/2726251.html

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

在上一章里,为了演示的方便,我们选择了一个简单的模型。但是如前所述,在实际的生产环境中,一方面我们的模型更为复杂,另一方面我们的贴图也不是普通的照片,而是处理过的uv图。uv图就是xyz三维图通过变换形成的二维图,类似数学里面学的极坐标变换。UV图的制作可以借用一些软件工具完成,在blender里面也有UV图编辑器。

这一节我们选用three.js官方例程中的一个加载头部模型的示例。原示例有三百多行代码,我把它精简到一百行多一点,包括扩了核心的uv图加载显示部分。而更多的处理代码则直接删掉,虽然显示效果因此差了一些,但精简的代码更适合说明和演示。

效果图如下:



对应的代码如下:

var container, loader;
var camera, scene, renderer;
var mesh, directionalLight;
var mouseX = 0, mouseY = 0;
var targetX = 0, targetY = 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( 35, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 900;
scene = new THREE.Scene();

// 添加光源
scene.add( new THREE.AmbientLight( 0x222222 ));

directionalLight = new THREE.DirectionalLight( 0xffeedd, 1 );
directionalLight.position.set( 1, -1, 1 ).normalize();
scene.add( directionalLight );

// 添加材质,其中包括uv图纹理
var ambient = 0x111111, diffuse = 0xbbbbbb, specular = 0x070707, shininess = 50;

specular = 0x555555;

var shader = THREE.ShaderSkin[ "skin" ];
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );

// normal纹理,diffuse纹理,涉及3D建模知识,目前还不了解具体意义
uniforms[ "tNormal" ].value = THREE.ImageUtils.loadTexture( "leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg" );
uniforms[ "uNormalScale" ].value = 0.75;

uniforms[ "tDiffuse" ].value = THREE.ImageUtils.loadTexture( "leeperrysmith/Map-COL.jpg" );

uniforms[ "passID" ].value = 1;

// 设置一些颜色值
uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
uniforms[ "uSpecularColor" ].value.setHex( specular );
uniforms[ "uAmbientColor" ].value.setHex( ambient );

uniforms[ "uRoughness" ].value = 0.185;
uniforms[ "uSpecularBrightness" ].value = 0.8;

var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true };

material = new THREE.ShaderMaterial( parameters );

// JSON加载器,需要自己指定uv贴图时一般都使用JSON加载器
loader = new THREE.JSONLoader( true );
document.body.appendChild( loader.statusDomElement );

// 回调中暴露加载的模型的形状
loader.load("leeperrysmith/LeePerrySmith.js", function( geometry ) {
geometry.computeTangents();

// 以加载的模型的geometry和代码创建的材质对象组建mesh对象加载到场景中显示
mesh = new THREE.Mesh( geometry, material );
mesh.position.y = - 50;
// scale参数一般是经验参数,自己调节获得
mesh.scale.set( 100, 100, 100 );

scene.add( mesh );
});

// 渲染
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColorHex( 0x050505, 1 );
renderer.autoClear = false;

container.appendChild( renderer.domElement );

// 鼠标移动事件,用来移动头部转动
document.addEventListener( 'mousemove', function ( event ) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}, false );
}

function animate() {
requestAnimationFrame( animate );

targetX = mouseX * .001;
targetY = mouseY * .001;

// 通过mesh的rotation实现动画,和之前旋转摄像机实现动画不同
if ( mesh ) {
// 目前尚不清楚0.05的参数如何计算得到,或许也是经验值,调节获得?
mesh.rotation.y += 0.05 * ( targetX - mesh.rotation.y );
mesh.rotation.x += 0.05 * ( targetY - mesh.rotation.x );
}

renderer.clear();
renderer.render( scene, camera );
}


对应的html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - materials - skin [Lee Perry-Smith]</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background:#000;
}
</style>
</head>

<body>
<script src="js/three.js"></script>
<script src="js/ShaderSkin.js"></script>
....
</body>
</html>


工程中用到了一些资源,最主要的就是模型的JSON文件:http://mrdoob.github.com/three.js/examples/obj/leeperrysmith/LeePerrySmith.js
然后是ShaderSkin.js的一个THREE扩展:http://mrdoob.github.com/three.js/examples/js/ShaderSkin.js,另外还有两个uv图片:http://mrdoob.github.com/three.js/examples/obj/leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg 和 http://mrdoob.github.com/three.js/examples/obj/leeperrysmith/Map-COL.jpg 

自己去试试吧!

 

另,吐槽一些个人感受,仅供参考。在探索Three.js的过程中,深感文档的缺失,不仅中文文档少到可怜,英文文档也极少。对初学者来说这是很恼火的事情。在无望之际,只能反复研究它的示例代码,然后做一点反向工程,通过不断的试验去确定某些函数或API的具体作用。虽然最后结果还不错,但回头想想,如果文档中对API介绍细致,同时配合详尽的示例文档,我花掉这么多时间做的探索或许就可以浓缩成半天的文档阅读了,这样能节省多少时间哪。这个现象本身也说明three.js还处在发展的初期,还有非常多的工作要做。所以对那些打算使用three.js做产品的同仁,希望能慎之又慎,否则很有可能陷入泥沼不能自拔。当然,对那些本身以具备丰富的3D建模知识的同仁来说,很多困难都不值一提,我非常希望这样的牛人能关注three.js这个领域,做一些普及工作,让这个领域在中国能向前迈进一大步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: