虚拟现实前传-Three.js实现管壳式换热器3D模型在线查看
- 2019 年 10 月 6 日
- 筆記
BGM:
使用threejs实现3D模型加载和显示。3D编程就像拍大片,几个关键东西如下所列:
- 场景师Sence,类似于舞台,重要性不言而喻,把一些杂七杂八的东西摆在舞台上(含演员),看起来像在现场一样;
- 灯光师Light,包括太阳这个顶级灯光,否则什么都看不到;
- 摄影师Camera,负责拍摄成像;
- 演员(含群众演员),例如各类静态Mesh(群演)、武打演员(动画[主演])等等;
- 道具如Texture、Material,负责演员衣服/化妆、场景纹理喷涂等;
- 武术动作指导:物理引擎Physics Engine;
- 导演兼视频编辑Renderer,负责协调摄影师、灯光师、场景师和演员道具等等;
好了,现在实现加载管壳式换热器stl模型。修改threejs官方stl加载案例源码(https://threejs.org/examples/?q=stl#webgl_loader_stl),代码如下:
<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - 管壳式换热器.STL</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <link type="text/css" rel="stylesheet" href="css/main.css"> <script src="js/three.min.js"></script> <script src="js/OrbitControls.js"></script> <script src="js/STLLoader.js"></script> <script src="js/stats.min.js"></script> </head> <body> <script type="module"> var container, stats, camera, scene, renderer; init(); animate(); function init() { container = document.createElement( 'div' ); document.body.appendChild( container ); camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 15 ); camera.position.set( 3, 0.15, 3 ); scene = new THREE.Scene(); scene.background = new THREE.Color( 0x72645b ); scene.fog = new THREE.Fog( 0x72645b, 2, 15 ); // Ground var plane = new THREE.Mesh( new THREE.PlaneBufferGeometry( 40, 40 ), new THREE.MeshPhongMaterial( { color: 0x999999, specular: 0x101010 } ) ); plane.rotation.x = - Math.PI / 2; plane.position.y = - 0.5; scene.add( plane ); plane.receiveShadow = true; // STLfile var loader = new THREE.STLLoader(); loader.load( './models/stl/demo.stl', function ( geometry ) { geometry.center(); var material = new THREE.MeshPhongMaterial( { color: 0xff5533, specular: 0x111111, shininess: 200 } ); var mesh = new THREE.Mesh( geometry, material ); mesh.scale.set( 0.001, 0.001, 0.001 ); mesh.castShadow = true; mesh.receiveShadow = true; scene.add( mesh ); } ); // Lights 玉帝说要有光,于是便有了光! scene.add( new THREE.HemisphereLight( 0x443333, 0x111122 ) ); addShadowedLight( 1, 1, 1, 0xffffff, 1.35 ); addShadowedLight( 0.5, 1, - 1, 0xffaa00, 1 ); // renderer renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.gammaInput = true; renderer.gammaOutput = true; renderer.shadowMap.enabled = true; container.appendChild( renderer.domElement ); // stats stats = new Stats(); container.appendChild( stats.dom ); // window.addEventListener( 'resize', onWindowResize, false ); var controls = new THREE.OrbitControls( camera, renderer.domElement ); controls.addEventListener( 'change', render ); } function addShadowedLight( x, y, z, color, intensity ) { var directionalLight = new THREE.DirectionalLight( color, intensity ); directionalLight.position.set( x, y, z ); scene.add( directionalLight ); directionalLight.castShadow = true; var d = 1; directionalLight.shadow.camera.left = - d; directionalLight.shadow.camera.right = d; directionalLight.shadow.camera.top = d; directionalLight.shadow.camera.bottom = - d; directionalLight.shadow.camera.near = 1; directionalLight.shadow.camera.far = 4; directionalLight.shadow.bias = - 0.002; } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } function animate() { requestAnimationFrame( animate ); render(); stats.update(); } function render() { renderer.render( scene, camera ); } </script> </body> </html>
程序分为几个步骤:
- 摄影师上场了,由于上个摄影师早上刚辞职,随便找了群众演员9527做临时摄影师,但貌似9527很愣,一动不动;
- 场景师布景,其实也没做什么,给导演做做样子;
- 演员上场,也就是今天主角:管壳式换热器水路计算域;但由于经费紧张,场景师只给了一件用纸糊的但金光闪闪的一次性外衣MeshPhongMaterial;
- 灯光师看见主演来了,不紧不慢上场,打开摄影棚窗户,随即又点亮两盏灯,并把灯光都给了主角管壳式换热器;
- 导演看人齐了,吩咐心腹小弟OrbitControls督促好摄影师不要愣站着,要摄影师满足各位看官大爷的请求。吩咐完,开始了拍摄工作…
出于安全,只能服务器上跑该程序,需要手工搭建简单服务器,使用nodejs(安装说明见2.5 node.js回首望,需要安装库static-server)搭建之,脚本如下:
var StaticServer = require('static-server'); var server = new StaticServer({ rootPath: './', port: 3000 }); server.start(function () { console.log('Server started on port ' + server.port); });
将该服务器脚本保存为server.js,与刚刚的网页保存为index.html,并置于同一目录下,在该目录下进入命令行工具,输入node server,启动服务器,浏览器输入127.0.0.1:3000,显示效果如下:
