three.js 08-03 之 加载和保存对象
前面介绍过,通过组合及合并等操作,你可以使用 three.js 提供的基本几何体来创建大型的、复杂的几何体。但是,如果你想创建更加高级的几何体,那么使用 three.js 所提供的编程方式就不是最好、最有效的方式。幸运的是 three.js 提供了其他多种从外部资源中创建并加载几何体和网格的方式。
下表所示就是 three.js 支持的几种常用的文件格式:
格式 | 描述 |
---|---|
JSON |
three.js 有它自己的 JSON 格式,你可以用它以声明的方式定义几何体和场景。但它并不是一种正式的格式。 它很容易使用,当你想要复用复杂的几何体或场景时非常有用 |
OBJ 和 MTL |
OBJ 是一种简单的三维文件格式,由 Wavefront 科技公司创立。它是使用最为广泛的三维文件格式,用来定义对象的几何体。 MTL 文件常同 OBJ 文件一起使用,在一个 MTL 文件中,对象的材质定义在 OBJ 文件中 |
Collada |
Collada 是一种用来定义 XML 类文件中数字内容的格式。这也是一种被广泛使用的格式,差不多所有的三维软件和渲染引擎 都支持这种格式 |
STL | STL 是 STereoLithography(立体成型术)的缩写,广泛用于快速成型。例如三维打印机的模型文件通常都是 STL 文件格式 |
three.js 有一个可定制的 STL 导出工具,STLExporter.js,你可以用它将 three.js 中的模型导出成一个 STL 文件 | |
CTM | CTM 是由 openCTM 创建的文件格式。可以用来压缩存储表示三维网格的三角形面片 |
VTK | VTK 是由 Visualization Toolkit 定义的文件格式,用来指定顶点和面。VTK 有两种格式,但 three.js 只支持旧有的 ASCII 格式 |
PDB |
PDB 是一种非常特别的格式,由 Protein Databank(蛋白质数据银行)创建,用来定义蛋白质的形状。three.js 可以加载并 显示用这种格式描述的蛋白质 |
PLY | PLY 格式的全称是多边形(polygon)文件格式。通常用来保存三维扫描仪的数据 |
一般来说针对以上每一种文件格式,three.js 都有一个相应的 Loder 来加载其数据。下面我们就来看看第一种 three.js 独有的格式,看看如何通过 three.js 相应的 API 来加载并保存其信息。
首先来看看如何保存并加载几何体。为了展示保存和加载几何体功能,我们基于 THREE.TorusKnotGeometry 类创建一个环面扭结,然后通过右上角的 Save & Load 菜单中的 Save 按钮来保存当前的几何体。在这个例子中我们使用了 H5 的本地存储 API 来把持久化信息保存到客户端浏览器里,而且以后还可以读取(即使在浏览器关闭并重启之后);保存后,可以通过右上角的 Save & Load 菜单中的 Load 按钮来加载用 Save 保存在本地存储的几何体。以下是本示例的完整代码:
<!DOCTYPE html>
<html>
<head><title>示例 08.03 - Load Save JSON Object</title><script src="../build/three.js"></script><script src="../build/js/controls/OrbitControls.js"></script><script src="../build/js/libs/stats.min.js"></script><script src="../build/js/libs/dat.gui.min.js"></script><script src="../jquery/jquery-3.2.1.min.js"></script><style>body {/* 设置 margin 为 0,并且 overflow 为 hidden,来完成页面样式 */margin: 0;overflow: hidden;}/* 统计对象的样式 */#Stats-output {position: absolute;left: 0px;top: 0px;}</style>
</head>
<body><!-- 用于 WebGL 输出的 Div -->
<div id="webgl-output"></div>
<!-- 用于统计 FPS 输出的 Div -->
<div id="stats-output"></div><!-- 运行 Three.js 示例的 Javascript 代码 -->
<script type="text/javascript">var scene;var camera;var render;var webglRender;//var canvasRender;var controls;var stats;var guiParams;var ambientLight;var spotLight;var axesHelper;//var cameraHelper;var ground;$(function() {initStats();initRender();initCamera();initControls();scene = new THREE.Scene();createAxesHelper();createAmbientLight();//createSpotLight();createGuiControls();// 加入地面//createGround()// 创建网格createMesh();renderScene();});/** 初始化 stats 统计对象 */function initStats() {stats = new Stats();stats.setMode(0); // 0 为监测 FPS;1 为监测渲染时间$('#stats-output').append(stats.domElement);return stats;}/** 初始化渲染器 */function initRender() {webglRender = new THREE.WebGLRenderer( {antialias: true, alpha: true} ); // antialias 抗锯齿webglRender.setSize(window.innerWidth, window.innerHeight);webglRender.setClearColor(0x0F0F0F, 1.0); // 0xeeeeeerender = webglRender;render.shadowMap.enabled = true; // 允许阴影投射$('#webgl-output')[0].appendChild(render.domElement);window.addEventListener('resize', onWindowResize, false);}/** 初始化相机 */function initCamera() {camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2147483647); // 2147483647camera.position.set(30, 40, 50);}/** 初始化鼠标控制器 */function initControls() {var target = new THREE.Vector3(0, 0 , 0);controls = new THREE.OrbitControls(camera, render.domElement);controls.target = target;camera.lookAt(target);}/** 当浏览器窗口大小变化时触发 */function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();render.setSize(window.innerWidth, window.innerHeight);}/** 渲染场景 */function renderScene() {stats.update();rotateMesh(); // 旋转物体requestAnimationFrame(renderScene);render.render(scene, camera);}/** 旋转物体 */var step = 0;function rotateMesh() {step += guiParams.rotationSpeed;scene.traverse(function(mesh) {if (mesh instanceof THREE.Mesh && mesh != ground) {//mesh.rotation.x = step;mesh.rotation.y = step;//mesh.rotation.z = step;}});}/** 创建一个坐标轴:X(橙色)、Y(绿色)、Z(蓝色) */function createAxesHelper() {axesHelper = new THREE.AxesHelper(60);scene.add(axesHelper);}/** 创建一个 AmbientLight 环境光源 */function createAmbientLight() {ambientLight = new THREE.AmbientLight(0x0c0c0c);scene.add(ambientLight);}/** 创建一个 AmbientLight 环境光源 */function createSpotLight() {spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-60, 60, -10);spotLight.castShadow = true;spotLight.shadow.mapSize.set(2048, 2048); // 必须是 2的幂,默认值为 512scene.add(spotLight);//cameraHelper = new THREE.CameraHelper(spotLight.shadow.camera);//scene.add(cameraHelper);}/** 用来保存那些需要修改的变量 */function createGuiControls() {guiParams = new function() {this.rotationSpeed = 0.02;this.radius = 10;this.tube = 0.3;this.tubularSegments = 64;this.radialSegments = 8;this.p = 2;this.q = 3;this.Save = function() {if (mesh) {var geoJSON = mesh.toJSON();console.log(geoJSON);localStorage.setItem('geoJSON', JSON.stringify(geoJSON));}};this.Load = function() {var geoJSON = localStorage.getItem('geoJSON');if (geoJSON) {var parsedGeom = JSON.parse(geoJSON);var loader = new THREE.ObjectLoader();var mesh = loader.parse(parsedGeom);mesh.material = new THREE.MeshBasicMaterial( { color: (Math.random() *0xffffff), wireframe: true } );mesh.position.set(0, 3, 0);mesh.name = "mesh";scene.remove(scene.getObjectByName(mesh.name));scene.add(mesh);}};}/** 定义 dat.GUI 对象,并绑定 guiParams 的几个属性 */var gui = new dat.GUI();var folder = gui.addFolder('Load & Save');folder.open();folder.add(guiParams, 'Save');folder.add(guiParams, 'Load');folder = gui.addFolder('Mesh');folder.add(guiParams, 'radius', 0, 40, 1).onChange( function(e) { createMesh(); } );folder.add(guiParams, 'tube', 0, 40, 0.1).onChange( function(e) { createMesh(); } );folder.add(guiParams, 'tubularSegments', 0, 400, 1).onChange( function(e) { createMesh(); } );folder.add(guiParams, 'radialSegments', 1, 20, 1).onChange( function(e) { createMesh(); } );folder.add(guiParams, 'p', 1, 10, 1).onChange( function(e) { createMesh(); } );folder.add(guiParams, 'q', 1, 15, 1).onChange( function(e) { createMesh(); } );}/** 加入地面 */function createGround() {var groundGeom = new THREE.PlaneGeometry(60, 60);var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xbbbbbb, side: THREE.DoubleSide} ); // 0x777777ground = new THREE.Mesh(groundGeom, groundMaterial);ground.receiveShadow = true; // 地面接收阴影ground.rotation.x = -0.5 * Math.PI;scene.add(ground);}/** 创建网格 */var material = new THREE.MeshBasicMaterial( { color: 0xbcbcbc, wireframe: true } );var mesh;function createMesh() {var geometry = new THREE.TorusKnotGeometry(guiParams.radius,guiParams.tube,guiParams.tubularSegments,guiParams.radialSegments,guiParams.p,guiParams.q);mesh = new THREE.Mesh(geometry, material);mesh.position.set(0, 3, 0);mesh.name = "mesh";scene.remove(scene.getObjectByName(mesh.name));scene.add(mesh);}</script>
</body>
</html>
顺便提一下,在旧有的 three.js 版本中,有专门的一个叫 GeometryExporter.js 的库来导出相应的信息。但是在新版 three.js 中,已经不需要借助任何外部的库就可以支持数据的导出。如本例中所使用的就是 THREE.Mesh 的 toJSON() 函数实现导出的。其实在新版 three.js 中,任何从 THREE.Object3D 类型继承而来的对象都可以通过其 toJSON() 函数来实现 JSON 格式的数据导出。随后就可以通过 THREE.ObjectLoader 对象的 parse() 函数或者 load() 函数反向解析出来。具体用法可以参考本示例中 createGuiControls() 函数中的 Save 及 Load 两个处理函数的代码。
未完待续···
three.js 08-03 之 加载和保存对象相关推荐
- c++版本opencv(02-第一个OpenCV程序 03.图像加载与保存)
c++版本opencv(02-第一个OpenCV程序) 一.02-第一个OpenCV程序 二,03.图像加载与保存 来自网易云课堂 一.02-第一个OpenCV程序 如果加载到了之后呢,我们就要对它进 ...
- Node.js(一、Node.js基础、模块加载机制、包等)
Node.js(一.Node.js基础.模块加载机制.包等) 1.Node.js基础 1.1.Node是什么 1.2.Node环境安装失败解决方法 1.2.1.Node环境搭建 1.2.2.错误代码2 ...
- php替换时 css中的图片不显示不出来,URL重写:CSS,JS和图像未加载
我遵循规则 .htaccess Options +FollowSymLinks RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAM ...
- JS里面的懒加载(lazyload)
懒加载技术(简称lazyload)并不是新技术, 它是js程序员对网页性能优化的一种方案.lazyload的核心是按需加载 涉及到图片,falsh资源 , iframe, 网页编辑器(类似FCK)等占 ...
- ajax加载vue数据,详解使用Vue.Js结合Jquery Ajax加载数据的两种方式
整理文档,搜刮出一个使用vue.js结合jquery ajax加载数据的两种方式的代码,稍微整理精简一下做下分享. 废话不多说,直接上代码 html代码 demo {{message }} 测试jqu ...
- Nginx相关 解决nginx反向代理后页面上的js/css文件无法加载
解决nginx反向代理后页面上的js/css文件无法加载 location ~ \.php$ {proxy_pass http://127.0.0.1:8000;include naproxy.con ...
- Node.js模块以及模块加载机制
2019独角兽企业重金招聘Python工程师标准>>> Node.js中的模块 在Node.js中,以模块为单位划分功能,通过一个完整的模块加载机制使得开发人员可以将应用程序划分为多 ...
- js 判断iframe是否加载完毕
js 判断iframe是否加载完毕 CreationTime--2018年9月13日15点30分 Author:Marydon 1.javascript实现 window.onload = funct ...
- 【前端】【cornerstone】cornerstone.js如何编辑图像/加载已有图像数据(以画直线为例)
[前端][cornerstone]cornerstone.js如何编辑图像/加载已有图像数据(以画直线为例) 首次加载图像 加载已有图像 部分参考博客:<cornerstone.js 使用总结& ...
- 【转】JS判断SWF,JPG加载完毕、兼容(Activex,plugIn)所有浏览器
JS判断SWF,JPG加载完毕.兼容(Activex,plugIn)所有浏览器 这里主要说下监听SWF的加载. 网上流传已久的监听方法,只能在IE(Activex插件下)下实现.在使用plugin的浏 ...
最新文章
- iMeta期刊顾问James M Tiedje当选中国科学院外籍院士
- win7多国语的安装说明
- Neo4j 导入动态类型关系
- OpenCV基于LeNet-5和连接组件分析的数字识别的实例(附完整代码)
- Spring5参考指南:AspectJ高级编程之Configurable
- pytorch实现人脸识别_一步一步带你完成深度学习与对象检测之人脸识别
- 如何在CDN边缘节点执行你的JavaScript?
- 华为交换机的端口hybrid端口属性配置
- Boosting and AdaBoost
- iOS FFmpeg 优秀博客(资源)集锦
- 立春好消息:华章图书持续霸榜京东、当当计算机畅销新书榜!
- 有道云笔记 markdown html,有道云笔记Markdown之流程图
- ios标准时间转为北京时间
- android 多版本共存,Android 多版本共存的处理方式
- 20221118-数学函数图像在线工具推荐
- java word 添加水印图片_Java添加Word文本水印和图片水印
- 一些软件黑盒测试工具列表
- 天河1号计算机配置,“天河一号”超级计算机配置抢先披露
- Core Audio I/O File Recording
- 二本师范类计算机专业的有哪些学校,全国师范大学排名是怎样的?二本师范类学校有哪些录取分数线多少...
热门文章
- AXI FULL协议学习与仿真
- 【PS】443种逼真度超高水彩笔刷打包下载
- 获取UI控件位置信息
- 聊一聊固态硬盘的那些事
- PVE解决VM is locked问题
- mysql视图代码_mysql创建视图的实例代码
- FDD/TDD协同优化
- mybatis order by concat用法
- 全桥驱动IR系列参考设计及问题指南
- Failed to compile../public/UEditor/dialogs/template/template.html 1:0Module parse failed: Unexpec