使用WebGL实现一个Viewer来显示STL文件
关键字:WebGL,STL,ThreeJS,Chrome,Viewer,Python3.4, HTML5,Canvas。
OS:Windows 10。
本文介绍如何使用ThreeJS来实现一个WebGL的Viewer,用来浏览STL文件。
<!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/
使用WebGL实现一个Viewer来显示STL文件的更多相关文章
- 与STL文件相关的各类学习地址
几个网址: 1.STL :https://en.wikipedia.org/wiki/STL_(file_format)#ASCII_STL 2.一个博客的文章地址: 三维图形数据格式 STL的 读取 ...
- 打开本地STL文件并创建webgl使用的geometry
需求 打开本地STL文件 一个独立基于webgl的viewer,会被别的网站重用 将打开文件的数据传输给viewer,并且在文件加载的时候显示进度条 解决方案 #1可以使用传统的html5 api来打 ...
- VTK中导入并显示STL、3DS文件
VTK(visualization toolkit)是一个开源的免费软件系统,主要用于三维计算机图形学.图像处理和科学计算可视化.VTK是在三维函数库OpenGL 的基础上采用面向对象的设计方法发展起 ...
- 使一个div始终显示在页面中间
使一个div始终显示在页面中间 假设我们有一个div层:<div id=”myDiv”></div> 首先,我们用css来控制它在水平上始终居中,那么我们的css代码应该是这样 ...
- 关于一个隐藏和显示物品列表的demo
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- Keil MDK 5.14 仿真时System Viewer菜单显示空白和Peripherals菜单无外设寄存器
keil mdk5.14新建工程进行仿真时,进入Debug环境发现System Viewer菜单显示空白,Peripherals菜单没有外设寄存器.如图1和图2所示.打开Oprons for Targ ...
- Sublime Text 如何一个代码双屏显示代码上下部分?
Sublime Text 如何一个代码双屏显示代码上下部分? sublime text如何一个代码双屏显示代码上下部分 先显示2行实图 把想要分屏显示的文件,打开新窗口,然后再拖过去就可以了. 快捷操 ...
- SharePoint server 2016中文版导出list template,在另外一个环境不能显示
SharePoint server 2016中文版导出list template,在另外一个环境不能显示,解决方案: $web = Get-SPWeb <url of web> $web. ...
- Qt for Android (三) 打开Android相册并选一个图片进行显示
Qt for Android (三) 这两天弄了一下android相册的相关功能.还是花了挺长时间的,这里总结一下,避免以后再踩坑.同时也在这篇文章里面补齐一些android开发的基础支持 打开And ...
随机推荐
- org.apache.hadoop.fs-BufferedFSInputStream
封装了FSInputStream package org.apache.hadoop.fs; import java.io.BufferedInputStream; import java.io.IO ...
- JavaFX(三)窗口拖动
1.问题场景 在上一篇中,我们将窗口的默认标题栏隐藏从而导致鼠标点击窗体无法进行拖动. 2.解决思路 给组件添加鼠标按下事件监听器和鼠标拖动事件监听器. 3.代码实现 代码片段: private do ...
- oracle顺序控制语句goto、null和分页过程中输入输出存储、java程序的调用过程
顺序控制语句1 goto建议不要使用 declare i number:=; begin loop dbms_output.put_line(i); then goto end_loop; end i ...
- (转)嵌入式学习准备---linux c 文件锁
(1)fcntl函数说明 前面的这5个基本函数实现了文件的打开.读写等基本操作,这一节将讨论的是,在文 件已经共享的情况下如何操作,也就是当多个用户共同使用.操作一个文件的情况,这时,Linux 通常 ...
- [转]T4模版引擎之生成数据库实体类
本文转自:http://www.cnblogs.com/lzrabbit/archive/2012/07/18/2597953.html 在通过T4模版引擎之基础入门 对T4有了初步印象后,我们开始实 ...
- CMS垃圾回收与G1垃圾回收
CMS垃圾回收与G1垃圾回收的比较请参见:http://colobu.com/2015/04/14/G1-Getting-Started/
- hdu 2412 树形DP
思路:对于最大的人数很容易想到,就直接dp.但对于最大值是否唯一就需要应用辅助数组,isOnly[i][0]表示dp[i][0]是否唯一,同理isOnly[i][1]. 那么当(dp[v][0]> ...
- Android 给应用定制皮肤
Android 给应用定制皮肤 导读:皮肤也就是相关的资源文件单独放置在某个工程中,一种皮肤一个工程文件.一个工程包括N多的资源文件,多个工程间资源的关系是,文件名,资源ID等完全一样. 在实现程序功 ...
- mac 如何进入/usr/sbin目录
1.进入terminal, 输入 ls /usr/sbin 2.在finder>前往文件夹,输入路径/usr/sbin
- .net System.Net.Mail 之用SmtpClient发送邮件 Demo
private static bool sendMail() { try { //接收人邮箱 string SendTo = "XXXXX@163.com"; //抄送人邮箱 st ...