百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

游戏编程 | Three.js 加载STL模型

suiw9 2024-10-26 14:29 34 浏览 0 评论

一直以来,如何对特定的模型进行读取和渲染操作是开发人员的难题。

储存3D模型的文件格式和标准:

  • .GLB
  • .GLTF
  • .STL
  • .json
    等等

我们这里介绍如何用Threejs导入.STL格式的模型。效果如下动图

1. STL模型的基本知识

STL 为 stereolithography 的缩写, 含义为光固化立体造型 术。 1988 年 3D SYSTEMS 公司将其制定为接口协议。 STL 是 一种为快速原型制造技术服务的三维图形文件格式。 由于其 具有解析简单, 文件体积较小等优点, 被广泛用于工业领域。 STL 将三角形作为基础图形, 对模型表面进行组织, 因此 十分适合在电子设备上进行绘制。 同时三角形的面可以表现 流畅的曲线, 使模型外观更加细腻, 所以说使用 STL 文件对 构建高质量模型发挥重要作用。 正是由于其具有上述特性, 最近发展异常火热的3D 打印技术都是以STL 作为标准格式。 STL 格式模型在 3DS Max 中的展示效果如图1 所示。

目前的 STL 文件格式包括二进制文件 (BINARY) 和文本 文件 (ASCII) 两种。 下面将分别对这两种格式的解析方法进 行介绍。

1.1 STL 文本文件的解析方法

STL 文本文件以行为单位顺序给出三角形面片的相关数 据。 每行的开头为一到两个关键字, 表明后面数据的相关含 义。 STL 文件中的关键字 facet 代表一个三角形面片的信息单 元。 此单元中包括关键字vertex 和 normal, 分别代表三角形的

顶点坐标和法向量数据。 若干个三角形面片相互组织就形成了最终的STL 三维模 型, 具体格式说明如下所示:

solid filename stl //自定义文件头 facet normal x y z //三角面片的法向量 outer loop vertex x y z //第一个顶点坐标 vertex x y z //第二个顶点坐标 vertex x y z //第三个顶点坐标 endloop endfacet //完成一个三角面片定义 … //省略了其他数据信息 endsolid filename stl //定义结束 

1.2 vscode 3d模型预览插件

1.3 threejs & STL

STL是STLereoLithography(立体成型术)的缩写,广泛用于快速成型。例如三维打印机的模型文件通常是STL文件。
Three.js对STL文件的加载器STLLoader.js,此文件封装了读取STL二进制文件和STL文本文件数据并初始化网格体的方法。
Three.js还有一个可定制的STL导出器,叫作OBJExporter.js,可以用来将Three.js中的模型导出到一个OBJ文件。

实现案例

案例查看地址:https://jxtreehouse.github.io/three.js-lessions/%E6%95%99%E7%A8%8B/examples/9_import_stl_model.html
首先,引入script加载器

<script src="/lib/js/loaders/STLLoader.js"></script>

加载STL模型之前,需要使用threejs对整个渲染场景进行初始化, 主要包括新建场景、设置摄像机位置和焦点、光源位置等相关操作。
渲染场景初始化工作完成以后,接下来就可以对STL模型进行加载了,主要思路:
 - 先创建一个STL格式的加载器
 - 创建完成后利用加载器load方法对模型进行加载,
    - load方法中第一个参数为STL模型所在位置和名称,
    - 第二个参数为STL文件读取完后,程序需要进行的一系列操作,通常包括设置模型的材质和设置缩放倍数
然后,实例化加载器对象,然后加载模型,STL模型里面只保存了几何体,所以我们实例化了一个纹理,添加到场景当中

var loader = new THREE.STLLoader();
loader.load("/lib/assets/models/SolidHead_2_lowPoly_42k.stl", function (geometry) {
    //创建纹理
    var mat = new THREE.MeshLambertMaterial({color: 0x00ffff});
    var mesh = new THREE.Mesh(geometry, mat);
    mesh.rotation.x = -0.5 * Math.PI; //将模型摆正
    mesh.scale.set(0.1, 0.1, 0.1); //缩放
    geometry.center(); //居中显示
    scene.add(mesh);
});

案例代码

1.2 vscode 3d模型预览插件<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        html, body {
            margin: 0;
            height: 100%;
        }

        canvas {
            display: block;
        }

    </style>
</head>
<body onload="draw();">

</body>
<script src="/lib/three.js"></script>
<script src="/lib/js/loaders/STLLoader.js"></script>
<script src="/lib/js/controls/OrbitControls.js"></script>
<script src="/lib/js/libs/stats.min.js"></script>
<script src="/lib/js/libs/dat.gui.min.js"></script>

<script>
    var renderer;
    function initRender() {
        // 新建渲染器
        renderer = new THREE.WebGLRenderer({antialias:true});
        renderer.setSize(window.innerWidth, window.innerHeight);
        //告诉渲染器需要阴影效果
        renderer.setClearColor(0xffffff);
        document.body.appendChild(renderer.domElement);
    }

    var camera;
    function initCamera() {
        camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
        // 设置摄像机位置和焦点
        camera.position.set(0, 40, 50);
        camera.lookAt(new THREE.Vector3(0,0,0));
  
    }

    var scene;
    function initScene() {
  // 新建场景
        scene = new THREE.Scene();
    }

    //初始化dat.GUI简化试验流程
    var gui;
    function initGui() {
        //声明一个保存需求修改的相关数据的对象
        gui = {
        };
        var datGui = new dat.GUI();
        //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)
    }

    var light;
    function initLight() {
        scene.add(new THREE.AmbientLight(0x444444));

        light = new THREE.PointLight(0xffffff);
  // 设置光源位置
        light.position.set(0,50,50);

        //告诉平行光需要开启阴影投射
        light.castShadow = true;
        // 添加光源到场景
        scene.add(light);
    }

    function initModel() {

        //辅助工具
        var helper = new THREE.AxesHelper(50);
        scene.add(helper);

        var loader = new THREE.STLLoader();
        loader.load("/lib/assets/models/SolidHead_2_lowPoly_42k.stl", function (geometry) {
            //创建纹理
            var mat = new THREE.MeshLambertMaterial({color: 0x00ffff});
            var mesh = new THREE.Mesh(geometry, mat);
            mesh.rotation.x = -0.5 * Math.PI; //将模型摆正
            mesh.scale.set(0.1, 0.1, 0.1); //缩放
            geometry.center(); //居中显示
            scene.add(mesh);
        });
    }

    //初始化性能插件
    var stats;
    function initStats() {
        stats = new Stats();
        document.body.appendChild(stats.dom);
    }

    //用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放
    var controls;
    function initControls() {

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

        // 如果使用animate方法时,将此函数删除
        //controls.addEventListener( 'change', render );
        // 使动画循环使用时阻尼或自转 意思是否有惯性
        controls.enableDamping = true;
        //动态阻尼系数 就是鼠标拖拽旋转灵敏度
        //controls.dampingFactor = 0.25;
        //是否可以缩放
        controls.enableZoom = true;
        //是否自动旋转
        controls.autoRotate = true;
        controls.autoRotateSpeed = 0.5;
        //设置相机距离原点的最远距离
        controls.minDistance  = 1;
        //设置相机距离原点的最远距离
        controls.maxDistance  = 200;
        //是否开启右键拖拽
        controls.enablePan = true;
    }

    function render() {

        renderer.render( scene, camera );
    }

    //窗口变动触发的函数
    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        render();
        renderer.setSize( window.innerWidth, window.innerHeight );

    }

    function animate() {
        //更新控制器
        render();

        //更新性能插件
        stats.update();

        controls.update();

        requestAnimationFrame(animate);
    }

    function draw() {
        initGui();
        initRender();
        initScene();
        initCamera();1.2 vscode 3d模型预览插件
        initLight();
        initModel();
        initControls();
        initStats();

        animate();
        window.onresize = onWindowResize;
    }
</script>
</html>

在线预览: https://jxtreehouse.github.io/three.js-lessions/%E6%95%99%E7%A8%8B/examples/9_import_stl_model.html


1.4 API 详解

  • WebGLRenderer
  • setSize()
  • .domElement
  • .PerspectiveCamera()
  • .AmbientLight()
  • .PointLight()
  • .AxesHelper()


相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: