用基于WebGL的BabylonJS来共享你的3D扫描模型
转自:http://www.geekfan.net/6578/
用基于WebGL的BabylonJS来共享你的3D扫描模型
本文由 极客范 - 杰克祥子 翻译自 Andy
Beaulieu。欢迎加入极客翻译小组,同我们一道翻译与分享。转载请参见文章末尾处的要求。
在这里,我们将展示如何在支持WebGL的浏览器中用BabylonJS来现实和优化彩色的3D扫描模型。我们会用 Kinect
for Windows来做3D扫描,当然你也可以用任何其它3D扫描仪。
点击下面的图片可以看到一些3D扫描的例子(请用支持WebGL的浏览器),一个猴子和一个果盘。
利用Kinect来做3D扫描已经有了一段时间,而且有一些商业软件,如ReconstructMe和Skanect,都提供了非常简单的使用界面。当然,这些软件也都有它们自己的局限,并且需要付费。
作为一个免费的替代方案,我们会用Kincect Fusion和Blender来创建并优化我们的3D扫描模型。然后,我们会用BabylonJS——一个JavaScript实现的、基于WebGL的3D显示和动画库,将我们的3D扫描共享到网络上。
第一步:准备工具
本文中,我们将会用到以下工具和软件库:
Kinect
for Windows SDK (和Developer Toolkit)
Kinect Fusion需要下载最新的SDK和Developer Toolkit。
我们用Blender,一个免费开源的3D设计工具,来优化我们的扫描模型以备网络共享使用。
这是一个用WebGL实现的、用来简化创建3D场景和游戏的JavaScript库。
github地址: https://github.com/BabylonJS/Babylon.js
BabylonJS
/ Blender Export Plug-in
这是一个用来将Blender的3D场景导出成Babylon格式的插件。下载并阅读连接中的安装指示操作,让它可以在Blender中使用。
github地址:https://github.com/BabylonJS/Babylon.js/tree/master/Exporters/Blender
第二步:用Kinect Fusion做3D扫描
首先打开安装Kinect Developer Toolkit时自带的Developer Toolkit Browser,找到Kinect Fusion Explorer – D2D那个例子。
Mesh Format一项选择PLY并且勾选Capture Color:
你还需要设置Reconstruction Volume和Voxel Resolution。对于我的扫描而言,我发现下面的参数是最合适的,但对于你而言可能需要试试其他参数。
扫描的时候你可以在Kinect的视图中旋转被扫描对象,或者绕着它走一圈。这次,我扫描了一个可爱的小猴子玩具。
当你扫描完所有的角度后,点击Create Mesh按钮,保存为PLY格式(颜色信息也会被保存)。
第三步:用Blender优化模型
此时,我们会得到一个很大的模型文件,为了能在浏览器中用BabylonJS来显示它,我们需要进一步优化模型(译者注:因为模型需要下载到浏览器才能通过WebGL来显示,所以更小的模型意味着更快的下载速度和显示速度)。我们还要清理模型并让它更平滑一点,因为3D扫描时总会有些意外的缺陷。所以我们需要Blender。如果你不熟悉Blender,可能第一次用的时候会有些困难,但必须坚持,它是一个有用且有趣的工具!当然,这里将不会包含所有使用Blender的基础技能和细节。
1)在CrowTreeStudios 可以学到如何做顶点颜色烘焙,这个视频演示了这些步骤。
2)打开Blender并按”X“键删除默认的立方体。
3)选择File->Import->Stanford (PLY)
a)打开你在第二步得到的PLY文件
b)这可能会花一会儿时间,因为扫描文件很大!
4)档模型加载完时,可能朝向是不对的,需要自己旋转并放置到中间,就像下图一样:
5)选中模型,然后选择Object->Duplicate Objects来复制一份。接下来,我们将减少顶点的数量,来优化复制的这个模型,并创建一个贴图来保存原始的颜色信息,也就是所谓的顶点烘焙。
重要提示:确保原始模型和复制的模型在完全一致的位置。这对顶点烘焙非常重要!两个模型需要完美的重合在一起。如果你需要调整,可以在Object Properties面板里手动设置位置X、Y、Z的值。
6)接下来,我们开始优化和清理模型,以得到一个更平滑、相对更小的模型文件。
a)隐藏原始的模型,这样你可以集中在复制的模型上。
b)选中复制的模型(Blender会给这个模型的名字后面加上“.001”)。
c)激活Modifies面板,选择Add Modifier。
d)选择Remesh并且设置Octree Depth为6,设置Mode为Smooth。观察模型的形状变化,你可能需要增加或者减少Octree
Depth以取得合适的平滑度和精细度。当你满意时,点击Apply。这将减少顶点的数量并让模型更平滑一点。
7)至此,复制的那份模型应该看上去更加平滑了,而且一些小缺陷也没有了:
a)让原始的模型可见,一起显示出来。
8)给原始的扫描模型添加材质
a)选中原始的模型
b)添加一个新材质
c)在Shading栏下面,选择“Shadeless”
d)在Options下面,勾选“Vertex Color Paint”
9)回到Blender的主视图,在“Viewport Shading”(小的球形图标)中选择“Texture”(这将会显示顶点的颜色数据)
10)现在,我们可以在原始模型上看到扫描的颜色了。下一步,我们将从这些颜色数据中创建一个贴图(也就是所谓的顶点烘焙)。
11)我们现在来为优化过的(复制的那份)模型添加一个材质
a)选中复制的那份模型
b)添加一个新材质
c)在Shading中选择“Shadeless”
12)然后,我们需要展开模型,是创建贴图的准备工作。
a)将Blender的视图切换为两个视图
b)在左侧的视图中,选中“UV/Image Editor”
c)在右侧的视图中,将复制的模型切换到Edit模式
d)选中所有的顶点
e)点击“U”键展开模型并选择“Smart UV Project”
13)创建一个图片来保存贴图。
a)在左侧的Image Editor中,创建一个新图片
b)为图片起个名字,并取消勾选“Alpha”,点击OK。
14)为了做顶点颜色烘焙,我们需要改变Blender默认的颜色管理。
a)选择Blender的Scene面板
b)在Color Management下,将Display Device设置为None。
15)现在我们来讲顶点的颜色数据烘焙到贴图。
a)找到Render面板(那个相机的图标)
b)选中高解析度的(原始的那份)模型
c)按住Shift并点击复制的那份模型(优化过的那份)。在你场景的树状图中,你可以看到原始模型的字体是黑色,复制模型的字体是白色:
16)下拉找到Bake(烘焙)菜单
a)勾选“Selected to active”
b)取消勾选“Clear”
c)点击Bake按钮
17)在左边的视图中,你可以看到顶点颜色都被烘焙到贴图中了:
18)保存贴图到本地文件。
a)在Image Editot菜单中选择Image/Save As Image
19)现在我们将贴图应用到优化过的那个模型上。
a)选中优化过的模型
b)添加一个新贴图
c)设置type=image或者movie
d)打开贴图文件
e)在Mapping栏中将Coordinates设置为UV
f)将Map设置为UVMap
20)现在我们有了贴图和优化过的模型,我们可以从项目中删掉原始模型了。
a)选中原始模型,选择Object->Delete来删除它。
21)将场景导出为Babylon的格式。
a)选择File->Export->Babylon JS(如果你没看到这个选项,那回到第一步,阅读关于插件的那节)
b)将会导出两个文件:一个*.babylon和一个*.png(贴图)文件。
第四步:用BabylonJS导入并显示模型
现在我们有了*.babylon的场景文件和*.png的贴图文件,用BabylonJS我们能很容易的将其导入并显示出来。
1)确定你的网页服务器开启了Babylon Mime Types。在IIS中,你需要在system.webserver中添加下面的一段(在configuration下面):
XHTML
1
2
3
4
5
|
<staticContent>
<!-- add mime types for babylon file types -->
<mimeMap fileExtension=".fx" mimeType="application/shader" />
<mimeMap fileExtension=".babylon" mimeType="application/babylon" />
</staticContent>
|
2)我们要用到两个从Babylon下载的脚本(将它们放在scripts子目录下):hand.js和Babylon.js
3)创建一个新HTML文件,加上下面的代码,用来从Blender导出的文件中创建Babylon的场景。
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<html>
<head>
<title>Simple
Babylon Demo</title>
<link
href="index.css" rel="stylesheet" />
<script
src="scripts/hand.js"></script>
<script
src="scripts/babylon.js"></script>
<script>
window.onload
= (function () {
var
canvas = document.getElementById("canvas");
//
Check that browser supports WebGL
if
(!BABYLON.Engine.isSupported()) {
document.getElementById("notSupported").className
= "";
document.getElementById("opacityMask").className
= "";
}
else {
//
create Babylon Engine
var
engine = new BABYLON.Engine(canvas, true);
//
create the Scene
var
scene = new BABYLON.Scene(engine);
//
add a light
var
light = new BABYLON.HemisphericLight("Hemi0", new BABYLON.Vector3(0, 1, 0), scene);
//
Add a camera that allows rotating view around a point
var
camera = new BABYLON.ArcRotateCamera("Camera", 0, 0.8, 100, new BABYLON.Vector3.Zero(), scene);
//
load the scene (exported from blender)
BABYLON.SceneLoader.ImportMesh("",
"images/models/", "monkey.babylon", scene, function (newMeshes, particleSystems) {
//
optional - position and size the mesh
var
monkey = newMeshes[0];
monkey.scaling.x
= 70;
monkey.scaling.y
= 70;
monkey.scaling.z
= 70;
monkey.position.z
= -48;
monkey.position.y
= 20;
monkey.position.x
= 0;
//
optional - add in a material and platform
var
platform = newMeshes[1];
platform.material
= new BABYLON.StandardMaterial("texture1", scene);
});
scene.activeCamera.attachControl(canvas);
//
register a render loop to render scene
engine.runRenderLoop(function
() {
scene.render();
});
//
Resize
window.addEventListener("resize",
function () {
engine.resize();
});
}
});
</script>
</head>
<body>
<div
id="opacityMask" class="hidden"></div>
<canvas
id="canvas"></canvas>
<div
id="notSupported" class="hidden">Your browser does not support WebGL</div>
</body>
</html>
|
结论
再提醒一下,你可以在这里和这里看到整个过程的两个例子。就像你所见,用WebGL来显示模型还需要一点额外的优化工作,但掌握这些我就可以最终控制模型的大小和细节。使用WebGL和BabylonJS,让我们有了无论在IE11、Firefox、Chrome、甚至一些移动平台的浏览器,都可以使用的跨平台的解决方案。
原文链接: Andy
Beaulieu 翻译: 极客范- 杰克祥子
译文链接: http://www.geekfan.net/6578/
[ 转载请保留原文出处、译者和译文链接。]
用基于WebGL的BabylonJS来共享你的3D扫描模型的更多相关文章
- 初学WebGL引擎-BabylonJS:第0篇-起因
学习WebGL的BabylonJS是在一次偶然的情况下进行的,主要为了满足个人对全栈开发的欲望. 言归正传,下面开始简单说说相关过程 WebGL是什么?WebGL是基于html的客户端页面技术,基于h ...
- 基于WebGL 的3D呈现A* Search Algorithm
http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现 ...
- 基于Redis缓存的Session共享(附源码)
基于Redis缓存的Session共享(附源码) 在上一篇文章中我们研究了Redis的安装及一些基本的缓存操作,今天我们就利用Redis缓存实现一个Session共享,基于.NET平台的Seesion ...
- PixiJS - 基于 WebGL 的超快 HTML5 2D 渲染引擎
Pixi.js 是一个开源的HTML5 2D 渲染引擎,使用 WebGL 实现,不支持的浏览器会自动降低到 Canvas 实现.PixiJS 的目标是提供一个快速且轻量级的2D库,并能兼容所有设备.此 ...
- 基于WebGL的三维的物联网平台技术
参加工作三年了,从一个搞调试的民工进阶为程序员,收获还是有那么一点的.慢慢讲一些. 去年在网上发现了https://hightopo.com/cn-index.html图扑软件的基于WebGL的三维j ...
- 基于SpringBoot+Redis的Session共享与单点登录
title: 基于SpringBoot+Redis的Session共享与单点登录 date: 2019-07-23 02:55:52 categories: 架构 author: mrzhou tag ...
- 基于OneMap的水利行业共享服务平台搭建步骤
今天上午再次学习Esri技术培训中心的“GIS服务共享与运维管理——之OneMap解决方案”课程,从中学习了OneMap的产品架构以及基于OneMap共享服务平台的搭建步骤.下面把其中水利行业的共享服 ...
- 一个基于WebGL的仿真3D水池有逼真的水波纹效果
最近在研究WebGL,看到国外很多高手做的很多超炫的3D效果,无比羡慕.忍不住把效果趴下来研究,下面介绍一个逼真的游泳池中浮动小球的效果.效果非常绚丽,功能强大.示例可切换观察水池的视角,不同视角考虑 ...
- 基于HTML5 Canvas 点击添加 2D 3D 机柜模型
今天又返回好好地消化了一下我们的数据容器 DataModel,这里给新手做一个典型的数据模型事件处理的例子作为参考.这个例子看起来很简单,实际上结合了数据模型中非常重要的三个事件处理的部分:属性变化事 ...
随机推荐
- poj 2186 强连通+缩点
题意:有一群牛,求被所有牛都认可的牛的个数 每个连通分量建一个缩点,出度为零的缩点包含的点的个数即为要求值 如果有多个出度为零的,直接输出零,否则输出那唯一一个出度为零的缩点包含的点的个数 #incl ...
- Set Time, Date Timezone in Linux from Command Line or Gnome | Use ntp
https://www.garron.me/en/linux/set-time-date-timezone-ntp-linux-shell-gnome-command-line.html Set ti ...
- winform设置超时时间
); //设置超时时间 var completedTask = await Task.WhenAny(new Task(async () => { );//执行的方法示例这里用延迟代替 }), ...
- Red Hat Linux虚拟机与主机共享文件
前置条件:linux上安装了VMware_Tool 参考https://dieyaxianju.cnblogs.com/EditPosts.aspx?postid=6829590 一.首先在本机上新建 ...
- Spark中常用的算法
Spark中常用的算法: 3.2.1 分类算法 分类算法属于监督式学习,使用类标签已知的样本建立一个分类函数或分类模型,应用分类模型,能把数据库中的类标签未知的数据进行归类.分类在数据挖掘中是一项重要 ...
- 【BZOJ 2351】 Matrix
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2351 [算法] 哈希 [代码] #include<bits/stdc++.h& ...
- php gd
imagecopy() 函数用于拷贝图像或图像的一部分. imagecopyresized() 函数用于拷贝部分图像并调整大小. imagecopy() imagecopy() 函数用于拷贝图像或图像 ...
- [牛客网练习赛 45 F] Magic Slab 解题报告 (最大权闭合子图)
interlinkage: https://ac.nowcoder.com/acm/contest/847/F description: solution: 最大权闭合子图; 每个单元格看成一个正权点 ...
- 21. Merge Two Sorted Lists[E]合并两个有序链表
题目 Merge two sorted linked lists and return it as a new list. The new list should be made by splicin ...
- NOIP 2012 D1T1 Vigenère密码
嗯嗯 一道找规律的题.... 真佩服那些把表打出来的人 //By SiriusRen #include <cstdio> #include <cstring> using na ...