Threejs之加载3D模型(上)

前言

Three.js 是一个基于 WebGLJavaScript 3D 库,它提供了丰富的 API 来在网页上创建和显示 3D 图形。加载 3D 模型到 Three.js 场景中是一个常见的需求,Three.js 支持多种格式的 3D 模型,如 .glb(GL Transmission Format Binary).gltf(GL Transmission Format).obj.fbx 等。下面将简要介绍如何使用 Three.js 加载 3D 模型。

一、模型类型

1.1 支持的模型类型

Three.js 支持加载多种模型文件格式,常见的包括:

  • glTF (.gltf .glb)glTF (GL Transmission Format) 是一种新型3D模型传输格式,具有高效、紧凑、支持PBR材质等优点,是三维模型的标准格式。
  • OBJ(.obj)OBJ是一种广泛使用的3D模型格式,支持几何体和材质信息,但不支持动画。
  • FBX(.fbx)FBX支持几何体、材质、骨骼动画等丰富信息,常用于3D内容制作和动画。
  • Collada (.dae)Collada支持几何体、材质、动画等丰富信息。
  • PLY (.ply)PLY (Polygon File Format或Stanford Triangle Format) 是一种用于存储3D扫描数据的格式,支持几何体和属性信息。
  • STL(.stI)STL (Stereolithography)是一种广泛用于3D打印的格式,主要支持几何体信息。
  • VRML(.wrl)VRML (Virtual Reality Modeling Language) 是一种早期的3D模型格式,支持几何体、材质和简单动画。
  • 3DS (.3ds)3DS:是Autodesk 3D Studio的格式,支持几何体、材质和简单动画。
  • JSON (.json)Three.jsJSON格式是一种自定义的模型格式,支持几何体材质、动画等信息。

1.2 模型加载器

Three.js提供了多种的加载器来加载以上的模型。例如:

  • GLTF加载器(GLTFLoader)glTF是专为高效传输与加载3D内容设计的开放格式,支持(.gltf)与二进制(.glb)格式。它整合了网格、材质、贴图、动画等丰富元素,并允许外部存储图像与数据,实现场景与资源的灵活传输。
  • OBJ加载器(OBJLoader)OBJ加载器处理3D几何数据,支持(.obj)格式。以易读方式存储顶点位置、UV`坐标、法线及多边形信息,简化3D模型的加载过程。
  • FBX加载器(FBXLoader)FBX是一种广泛使用的3D模型文件格式,支持(.fbx)格式。它可以包含几何形状、材质、动画、骨骼等多种数据,因此在游戏开发、虚拟现实、电影制作等领域有着广泛的应用。
  • DAE加载器(ColladaLoader):用于加载和处理Collada(.dae)格式3D模型文件的扩展。Collada是一种基于XML的3D内容格式,广泛用于三维软件和渲染引擎中,因为它不仅定义了模型的几何体,还包含了材质、光源等多种信息。
  • PLY加载器(PLYLoader):用于加载PLYPolygon File Format,多边形文件格式)格式3D模型文件的加载器。支持(.ply)格式。PLY格式主要用于存储简单的3D几何数据,包括顶点、颜色、法线和UV坐标等,支持二进制和ASCII格式。
  • STL加载器(STLLoader):用于加载STLStereolithography,立体成型术)文件的类。STL文件广泛用于3D打印和计算机辅助设计(CAD)应用程序中,支持(.stl)格式。它包含了模型的几何信息,但通常不包含材质、颜色或纹理信息。
  • WRL加载器(VRMLLoader):用于加载VRMLVirtual Reality Modeling Language,虚拟现实建模语言)文件的加载器。支持(.wrl)格式。尽管VRML是一种较老的、基于文本的格式,用于定义三维对象和世界,但它在某些特定场合或历史项目中仍然有其应用价值。
  • 3DS加载器(TDSLoader):用于加载3DS3D Studio)文件的加载器。3DS文件是由Autodesk3ds Max软件创建的三维模型文件,它包含了模型的几何形状、材质、动画等信息。
  • JSON加载器(JSONLoader):用于加载JSON格式3D模型文件的加载器。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。

二、常用模型加载器

2.1 代码示例

2.1.1 GLTFLoader

2.1.1.1 代码

构造函数
GLTFLoader( filepath, gltfCallback, progressCallback, errorCallback )
代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <script type="module">
        // 倒入轨道控制器
        import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
        import * as THREE from 'three';
        import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
        // 创建场景
        const scene = new THREE.Scene();
        scene.background = new THREE.Color(0xffffff);
        // 创建相机
        const camera = new THREE.PerspectiveCamera( // 透视相机
            45, // 视角 角度数
            window.innerWidth / window.innerHeight, // 宽高比 占据屏幕
            0.1, // 近平面(相机最近能看到物体)
            1000, // 远平面(相机最远能看到物体)
        );
        camera.position.set(0, 2, 40);
        // 创建渲染器
        const renderer = new THREE.WebGLRenderer({
            antialias: true, // 抗锯齿
        });
        // 设置渲染器宽高
        renderer.setSize(window.innerWidth, window.innerHeight);
        // renderer(渲染器)的dom元素添加到我们的HTML文档中
        document.body.appendChild(renderer.domElement);
        // 加入灯光
        const light = new THREE.PointLight(0xffffff, 900, 100);
        light.position.set(20, 20, 10);
        const pointLightHelper = new THREE.PointLightHelper(light, 3);
        scene.add(pointLightHelper);

        scene.add(light);
        const ambientLight = new THREE.AmbientLight(0x404040, 100); // 柔和的白光
        scene.add(ambientLight);
        // 地面
        const plane = new THREE.Mesh(
            new THREE.PlaneGeometry(80, 80),
            new THREE.MeshStandardMaterial({ color: 0x817936 })
        );
        plane.rotation.x = -Math.PI / 2;
        // 添加到场景中
        scene.add(plane);
        renderer.shadowMap.enabled = true;
        renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 更好的阴影质量
        renderer.shadowMap.needsUpdate = true;
        plane.receiveShadow = true;
        light.castShadow = true;

        // 导入模型
        const gltfLoader = new GLTFLoader();
        gltfLoader.load("../models/pingzi.glb", (gltf) => {
            console.log(gltf.scene.traverse);
            // 设置模型的材质以接受阴影
            gltf.scene.traverse((child) => {
                if (child.isMesh) {
                    console.log(child)
                    child.castShadow = true; // 让模型产生阴影
                    // child.receiveShadow = true; // 让模型接受阴影
                }
            });
            // 设置模型缩放
            gltf.scene.scale.set(0.1, 0.1, 0.1);
            // 设置模型位置
            gltf.scene.position.set(0, 5.5, 0);
            scene.add(gltf.scene);
        },
            // called while loading is progressing
            (xhr) => {
                console.log((xhr.loaded / xhr.total * 100) + '% loaded');
            },
            // called when loading has errors
            (error) => {
                console.log('An error happened', error);
            })

        // 控制器
        const control = new OrbitControls(camera, renderer.domElement);
        // 开启阻尼惯性,默认值为0.05
        control.enableDamping = true;

        // 渲染循环动画
        function animate() {
            // 在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)
            requestAnimationFrame(animate);
            // 更新控制器。如果没在动画里加上,那必须在摄像机的变换发生任何手动改变后调用
            control.update();
            renderer.render(scene, camera);
        };

        // 执行动画
        animate();
    </script>
</body>
</html>
2.1.1.2 效果

请添加图片描述
可以看到我们就把.glb后缀多模型文件加载进来了,它是一个玻璃瓶子。

在学习的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你华还是你华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值