使用WebGL实现一个Viewer来显示STL文件

关键字:WebGL,STL,ThreeJS,Chrome,Viewer,Python3.4, HTML5,Canvas。

OS:Windows 10。

 

本文介绍如何使用ThreeJS来实现一个WebGL的Viewer,用来浏览STL文件。

STL 文件是在计算机图形应用系统中,用于表示三角形网格的一种文件格式。 它的文件格式非常简单, 应用很广泛。
STL是最多快速原型系统所应用的标准文件类型。STL是用三角网格来表现3D CAD模型。
 
 
1.新建一个STL.html文件如下:
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>WebViewer - STL</title>
        <meta charset="utf-8">
    </head>
    <body>
        <script src="threejs/three.min.js"></script>
        <script src="threejs/loaders/STLLoader.js"></script>
        <script src="threejs/OrbitControls.js"></script>

        <script>
            var container;

            var camera, cameraTarget, scene, renderer;
            
            var cameraType = 1;
            var perspectiveAngle = 45;
            var cameraPosX = 200;
            var cameraPosY = 200;
            var cameraPosZ = 200;
            var cameraTargetX = 0;
            var cameraTargetY = 0;
            var cameraTargetZ = 0;
            var upVectorX = 0;
            var upVectorY = 1;
            var upVectorZ = 0;
            var cameralScale = 5;
            
            init();
            animate();
            
            function getQueryStringByName(name){
                 var result = location.search.match(new RegExp("[\?\&]" + name+ "=([^\&]+)","i"));
                
                 if(result == null || result.length < 1){
                     return "";
                 }

                 return result[1];
            }

            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );
                
                // set camera
                var cameraTypeStr = getQueryStringByName('cameraType');
                cameraType = cameraTypeStr == "" ? cameraType : parseInt(cameraTypeStr);
                
                var perspectiveAngleStr = getQueryStringByName('perspectiveAngle');
                perspectiveAngle = perspectiveAngleStr == "" ? perspectiveAngle : parseFloat(perspectiveAngleStr);
                
                var cameraPosXStr = getQueryStringByName('cameraPosX');
                cameraPosX = cameraPosXStr == "" ? cameraPosX : parseFloat(cameraPosXStr) * cameralScale;
                
                var cameraPosYStr = getQueryStringByName('cameraPosY');
                cameraPosY = cameraPosYStr == "" ? cameraPosY : parseFloat(cameraPosYStr) * cameralScale;
                
                var cameraPosZStr = getQueryStringByName('cameraPosZ');
                cameraPosZ = cameraPosZStr == "" ? cameraPosZ : parseFloat(cameraPosZStr) * cameralScale;
                
                var cameraTargetXStr = getQueryStringByName('cameraTargetX');
                cameraTargetX = cameraTargetXStr == "" ? cameraTargetX : parseFloat(cameraTargetXStr) * cameralScale;
                
                var cameraTargetYStr = getQueryStringByName('cameraTargetY');
                cameraTargetY = cameraTargetYStr == "" ? cameraTargetY : parseFloat(cameraTargetYStr) * cameralScale;
                
                var cameraTargetZStr = getQueryStringByName('cameraTargetZ');
                cameraTargetZ = cameraTargetZStr == "" ? cameraTargetZ : parseFloat(cameraTargetZStr) * cameralScale;
                
                var upVectorXStr = getQueryStringByName('upVectorX');
                upVectorX = upVectorXStr == "" ? upVectorX : parseFloat(upVectorXStr) * cameralScale;
                
                var upVectorYStr = getQueryStringByName('upVectorY');
                upVectorY = upVectorYStr == "" ? upVectorY : parseFloat(upVectorYStr) * cameralScale;
                
                var upVectorZStr = getQueryStringByName('upVectorZ');
                upVectorZ = upVectorZStr == "" ? upVectorZ : parseFloat(upVectorZStr) * cameralScale;
                
                if(cameraType == 0) {
                    camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 10000 );
                }
                else {
                    camera = new THREE.PerspectiveCamera( perspectiveAngle, window.innerWidth / window.innerHeight, 1, 10000 );
                }
            
                camera.position.set( cameraPosX, cameraPosY, cameraPosZ);
                camera.up.set(upVectorX, upVectorY, upVectorZ);

                cameraTarget = new THREE.Vector3( cameraTargetX, cameraTargetY, cameraTargetZ );
                camera.lookAt( cameraTarget );

                scene = new THREE.Scene();
                scene.fog = new THREE.Fog( 0xffffff, 1, 10000 );

                // load file

                var loader = new THREE.STLLoader();
                
                var modelName = getQueryStringByName('modelName');
                loader.load( '../Models/' + modelName, function ( geometry ) {

                    var material = new THREE.MeshPhongMaterial( { color: 0x808080, specular: 0x111111, shininess: 200 } );
                    var mesh = new THREE.Mesh( geometry, material );

                    mesh.castShadow = true;
                    mesh.receiveShadow = true;

                    scene.add( mesh );

                } );

                // lights

                scene.add( new THREE.AmbientLight( 0x333333 ) );
                
                addDirectionalLight(-1, 1, 1, 0xFFFFFF, 1.35);
                addDirectionalLight(1, -1, -1, 0xFFFFFF, 1);

                // renderer

                renderer = new THREE.WebGLRenderer( { antialias: true } );
                renderer.setClearColor( scene.fog.color );
                renderer.setSize( window.innerWidth, window.innerHeight );

                renderer.gammaInput = true;
                renderer.gammaOutput = true;

                renderer.shadowMapEnabled = true;
                renderer.shadowMapCullFace = THREE.CullFaceBack;

                container.appendChild( renderer.domElement );
                
                // orbit control

                control = new THREE.OrbitControls( camera, renderer.domElement );

                // events

                window.addEventListener( 'resize', onWindowResize, false );
            }
            
            function addDirectionalLight( x, y, z, color, intensity ) {

                var directionalLight = new THREE.DirectionalLight( color, intensity );
                directionalLight.position.set( x, y, z )
                scene.add( directionalLight );
            }
            
            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }

            function animate() {

                requestAnimationFrame( animate );

                render();
            }

            function render() {

//                var timer = Date.now() * 0.0005;
//
//                camera.position.x = Math.cos( timer ) * 3;
//                camera.position.z = Math.sin( timer ) * 3;

                renderer.render( scene, camera );
            }

        </script>
    </body>
</html>

 

2.直接用Chrome打开文件STL.html,将会看到一下错误,那是因为不能打开本地模型文件,需要创建一个http server。

XMLHttpRequest cannot load file:///D:/L/Dev/WebViewer/Models/. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.THREE.XHRLoader.load @ three.min.js:258
three.min.js:258 Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'file:///D:/L/Dev/WebViewer/Models/'.

 

3.本文使用python来创建一个http server,新建localServer.py文件,内容如下:

from threading import Thread
import webbrowser, http.server, socketserver
import time;

port_number = 8000

server = None
def startServer(port):
    Handler = http.server.SimpleHTTPRequestHandler
    global server
    server = socketserver.TCPServer(("", port), Handler)

    print("Start server at port", port)
    server.serve_forever()
   
def start(port):
    thread = Thread(target=startServer, args=[port])
    thread.start()
    
    startTime = int(time.time())
    while not server:
        if int(time.time()) > startTime + 60:
            print("Time out")
            break
    return server

def stop():
    if server:
        server.shutdown()
        
def openUrl():
    url = "http://localhost:" + str(port_number)
    webbrowser.open(url)
    print(url + " is opened in browser")

if __name__ == "__main__":
    start(port_number)
    openUrl()

 

4.文件夹结构如下:

Models - 模型文件夹,放置模型文件,例如bike_frame.stl。

threejs - threejs文件夹,放置threejs相关的库文件

 

5. 双击运行LocalServer.py启动一个http服务器。

 

6.在Chrome里面打开http://localhost:8000/WebGLViewer/STL.html?modelName=bike_frame.stl,如下图。

 

源代码地址:https://github.com/ldlchina/Sample-of-WebGL-with-STL-loader

相关链接: http://threejs.org/

posted @ 2015-09-01 23:24  Ldlchina  阅读(8535)  评论(1编辑  收藏  举报