使用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 ...
随机推荐
- Boxes in a Line
Boxes in a Line You have n boxes in a line on the table numbered 1 . . . n from left to right. Your ...
- B. Painting Pebbles
B. Painting Pebbles time limit per test 1 second memory limit per test 256 megabytes input standard ...
- (重刷)HDU 1874 畅通工程续 + HDU 2544 最短路 最短路水题,dijkstra解法。
floyd解法 今天初看dijkstra,先拿这两题练手,其他变形题还是不是很懂. 模版题,纯练打字... HDU 1874: #include <cstdio> #define MAXN ...
- 【极角排序、扫描线】UVa 1606 - Amphiphilic Carbon Molecules(两亲性分子)
Shanghai Hypercomputers, the world's largest computer chip manufacturer, has invented a new class of ...
- Win7 32bit(x86)/64bit(x64) 完整安装版(非GHOST版本)
Windows7 32bit 旗舰iso格式完整安装镜像 百度云盘:http://pan.baidu.com/s/1bpjLPs Windows7 64bit 旗舰iso格式完整安装镜像 百度云盘:h ...
- jquery 60秒倒计时(方法二)
<script type="text/javascript">var wait=60;document.getElementById("btn"). ...
- Nginx - HTTP Configuration, Module Variables
The HTTP Core module introduces a large set of variables that you can use within the value of direct ...
- CSS之鼠标经过字体光标形状的改变
CSS中的cursor属性是规定要显示的光标的类型(形状). 参阅JavaScript正则表达式 default 默认光标(通常是一个箭头) auto 默认.浏览器设置的光标. crosshair 光 ...
- jQuery 的插件 dataTables
---恢复内容开始--- jQuery 的插件 dataTables 是一个优秀的表格插件,提供了针对表格的排序.浏览器分页.服务器分页.筛选.格式化等功能.dataTables 的网站上也提供了大量 ...
- jQuery 自定义事件的学习笔记
jquery中提供了两种方法可以绑定自定义事件: bind()和one()而绑定的自定义事件的触发,必须得用jquery中的trigger()方法才能触发. 我们先来看on事件 代码如下 复制代码 ...