当前位置: 首页 > article >正文

大白话react第十八章

大白话react第十八章React 与 WebGL 项目的高级拓展与优化

1. 实现 3D 模型的导入与动画

在之前的基础上,我们可以导入更复杂的 3D 模型,并且让这些模型动起来,就像在游戏里看到的角色和场景一样。这里我们使用 GLTF 格式的模型,它是一种常用的 3D 模型格式,并且 three.js 提供了很好的支持。

// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 用于加载 GLTF 格式的 3D 模型
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const ModelAnimationComponent = () => {
    // 创建一个 ref 用于引用存放 3D 场景的 DOM 元素
    const containerRef = useRef(null);

    useEffect(() => {
        // 创建 three.js 的场景
        const scene = new THREE.Scene();
        // 创建透视相机,设置视角、宽高比、近裁剪面和远裁剪面
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 创建 WebGL 渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染器的大小为窗口大小
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 将渲染器的 DOM 元素添加到 ref 对应的 DOM 元素中
        containerRef.current.appendChild(renderer.domElement);

        // 创建一个环境光,让场景整体更亮
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
        scene.add(ambientLight);

        // 创建一个点光源,让物体有明暗对比
        const pointLight = new THREE.PointLight(0xffffff, 1);
        pointLight.position.set(2, 5, 2);
        scene.add(pointLight);

        // 创建一个 GLTF 加载器
        const loader = new GLTFLoader();
        // 加载 GLTF 格式的 3D 模型
        loader.load('path/to/your/model.gltf', (gltf) => {
            // 获取加载的模型
            const model = gltf.scene;
            // 将模型添加到场景中
            scene.add(model);

            // 如果模型有动画
            if (gltf.animations.length > 0) {
                // 创建一个动画混合器,用于管理动画
                const mixer = new THREE.AnimationMixer(model);
                // 获取第一个动画
                const action = mixer.clipAction(gltf.animations[0]);
                // 播放动画
                action.play();

                // 定义渲染函数
                const animate = () => {
                    // 请求下一帧动画
                    requestAnimationFrame(animate);
                    // 更新动画混合器
                    mixer.update(0.01);
                    // 渲染场景
                    renderer.render(scene, camera);
                };

                // 开始动画循环
                animate();
            }
        });

        // 设置相机位置
        camera.position.z = 5;

        // 组件卸载时清理资源
        return () => {
            containerRef.current.removeChild(renderer.domElement);
        };
    }, []);

    return (
        // 创建一个 div 用于存放 3D 场景
        <div ref={containerRef} />
    );
};

export default ModelAnimationComponent;
2. 实现多场景切换

在一些大型的 3D 应用中,可能需要多个不同的场景,并且能够在这些场景之间自由切换。我们可以通过管理多个场景对象,根据用户的操作来显示不同的场景。

// 引入 React 的 useEffect、useRef 和 useState 钩子
import React, { useEffect, useRef, useState } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';

const MultiSceneComponent = () => {
    // 创建一个 ref 用于引用存放 3D 场景的 DOM 元素
    const containerRef = useRef(null);
    // 创建一个状态来存储当前显示的场景索引
    const [currentSceneIndex, setCurrentSceneIndex] = useState(0);

    useEffect(() => {
        // 创建两个 three.js 的场景
        const scenes = [new THREE.Scene(), new THREE.Scene()];
        // 创建透视相机,设置视角、宽高比、近裁剪面和远裁剪面
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 创建 WebGL 渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染器的大小为窗口大小
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 将渲染器的 DOM 元素添加到 ref 对应的 DOM 元素中
        containerRef.current.appendChild(renderer.domElement);

        // 为第一个场景添加一个立方体
        const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);
        const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        scenes[0].add(cube);

        // 为第二个场景添加一个球体
        const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
        const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        scenes[1].add(sphere);

        // 设置相机位置
        camera.position.z = 5;

        // 定义渲染函数
        const animate = () => {
            // 请求下一帧动画
            requestAnimationFrame(animate);
            // 获取当前要显示的场景
            const currentScene = scenes[currentSceneIndex];
            // 渲染当前场景
            renderer.render(currentScene, camera);
        };

        // 开始动画循环
        animate();

        // 组件卸载时清理资源
        return () => {
            containerRef.current.removeChild(renderer.domElement);
        };
    }, [currentSceneIndex]);

    return (
        <div>
            {/* 创建一个 div 用于存放 3D 场景 */}
            <div ref={containerRef} />
            {/* 创建按钮用于切换场景 */}
            <button onClick={() => setCurrentSceneIndex(0)}>切换到场景 1</button>
            <button onClick={() => setCurrentSceneIndex(1)}>切换到场景 2</button>
        </div>
    );
};

export default MultiSceneComponent;
3. 实现 WebGL 与后端数据交互

有时候我们需要从后端获取数据,然后根据这些数据来更新 3D 场景。这里我们模拟一个从后端获取数据的过程,然后根据数据来改变 3D 物体的属性。

// 引入 React 的 useEffect、useRef 和 useState 钩子
import React, { useEffect, useRef, useState } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';

const DataInteractionComponent = () => {
    // 创建一个 ref 用于引用存放 3D 场景的 DOM 元素
    const containerRef = useRef(null);
    // 创建一个状态来存储从后端获取的数据
    const [data, setData] = useState(null);

    useEffect(() => {
        // 模拟从后端获取数据
        const fetchData = async () => {
            try {
                const response = await fetch('https://example.com/api/data');
                const jsonData = await response.json();
                setData(jsonData);
            } catch (error) {
                console.error('获取数据失败:', error);
            }
        };

        fetchData();
    }, []);

    useEffect(() => {
        if (data) {
            // 创建 three.js 的场景
            const scene = new THREE.Scene();
            // 创建透视相机,设置视角、宽高比、近裁剪面和远裁剪面
            const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            // 创建 WebGL 渲染器
            const renderer = new THREE.WebGLRenderer();
            // 设置渲染器的大小为窗口大小
            renderer.setSize(window.innerWidth, window.innerHeight);
            // 将渲染器的 DOM 元素添加到 ref 对应的 DOM 元素中
            containerRef.current.appendChild(renderer.domElement);

            // 根据后端数据创建一个立方体
            const cubeGeometry = new THREE.BoxGeometry(data.size, data.size, data.size);
            const cubeMaterial = new THREE.MeshBasicMaterial({ color: data.color });
            const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            scene.add(cube);

            // 设置相机位置
            camera.position.z = 5;

            // 定义渲染函数
            const animate = () => {
                // 请求下一帧动画
                requestAnimationFrame(animate);
                // 渲染场景
                renderer.render(scene, camera);
            };

            // 开始动画循环
            animate();

            // 组件卸载时清理资源
            return () => {
                containerRef.current.removeChild(renderer.domElement);
            };
        }
    }, [data]);

    return (
        // 创建一个 div 用于存放 3D 场景
        <div ref={containerRef} />
    );
};

export default DataInteractionComponent;

通过这些高级拓展和优化,你的 React 与 WebGL 项目会变得更加复杂和强大,能够满足更多的实际需求。

GLTF格式的特点和优势

GLTF 格式的特点和优势介绍

什么是 GLTF 格式

GLTF 就像是一个专门用来装 3D 模型和场景的“盒子”,它能把 3D 世界里的各种东西,像模型的形状、颜色、动画这些信息,有条理地打包起来,方便在不同的地方使用。

特点
1. 轻量化

GLTF 格式很“轻”,就好比一个轻装上阵的运动员。它不会携带一堆没用的东西,只装真正需要的信息。这样在传输的时候,速度就会很快,就像快递送一个很轻的包裹一样。而且它用一种叫 JSON 的格式来记录模型的基本信息,这种格式简单易懂,计算机处理起来也不费劲。

2. 通用性强

不管你用的是电脑、手机,还是其他什么设备,只要这个设备能处理 3D 内容,基本上都能打开 GLTF 格式的文件。就像一把万能钥匙,能开很多不同的“锁”,在各种 3D 软件、游戏引擎里都能使用。

3. 支持动画和材质

GLTF 可以把模型的动画也一起打包进去。想象一下,一个 3D 人物模型,它走路、跑步、挥手这些动作的动画,都能和模型本身放在一个“盒子”里。同时,它还能记录模型的材质信息,比如这个模型看起来是金属的、木头的,还是塑料的,都能清晰地表现出来。

4. 二进制扩展

除了基本的 JSON 格式,GLTF 还有二进制扩展。这就好比在原来的“盒子”外面又加了一个更结实的“外套”,能把一些更复杂、更占空间的数据,像模型的顶点数据,用二进制的方式存储,这样能让文件更小,读取速度也更快。

优势
1. 加载速度快

因为文件轻,所以在网页或者应用里加载 GLTF 格式的 3D 模型时,速度会非常快。用户不用等很长时间,就能看到模型,体验就会很好。

2. 易于编辑和共享

由于它的结构清晰,开发者很容易对 GLTF 文件进行编辑和修改。而且因为通用性强,不同的人之间分享这个格式的文件也很方便,大家都能打开和使用。

3. 跨平台兼容性好

不管是在电脑上的浏览器里,还是在手机的 APP 中,GLTF 格式的模型都能正常显示和使用。这样就可以让更多的人在不同的设备上体验到 3D 内容。

代码示例(使用 Three.js 加载 GLTF 模型)
// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 库,用于创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 模块,专门用于加载 GLTF 格式的文件
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

// 定义一个 React 组件,用于展示加载的 GLTF 模型
const GLTFModelComponent = () => {
    // 创建一个 ref 对象,用于引用后续要添加 3D 场景的 DOM 元素
    const containerRef = useRef(null);

    useEffect(() => {
        // 创建一个 three.js 的场景对象,相当于一个 3D 世界的舞台
        const scene = new THREE.Scene();
        // 创建一个透视相机,设置视角、宽高比、近裁剪面和远裁剪面
        // 就像我们用相机拍照一样,确定我们看 3D 场景的视角和范围
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 创建一个 WebGL 渲染器,它的作用是把 3D 场景渲染成我们能看到的 2D 画面
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染器的大小为窗口的宽度和高度,让场景能占满整个窗口
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 将渲染器生成的 DOM 元素添加到之前创建的 ref 对应的 DOM 元素中
        containerRef.current.appendChild(renderer.domElement);

        // 创建一个环境光,让整个场景有一个基本的亮度,就像打开房间里的大灯
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
        // 将环境光添加到场景中
        scene.add(ambientLight);

        // 创建一个点光源,它就像一个手电筒,可以照亮特定的区域
        const pointLight = new THREE.PointLight(0xffffff, 1);
        // 设置点光源的位置
        pointLight.position.set(2, 5, 2);
        // 将点光源添加到场景中
        scene.add(pointLight);

        // 创建一个 GLTFLoader 实例,用于加载 GLTF 文件
        const loader = new GLTFLoader();
        // 加载指定路径的 GLTF 文件
        // 第一个参数是文件的路径,第二个参数是加载成功后的回调函数
        loader.load('path/to/your/model.gltf', (gltf) => {
            // 获取加载的 GLTF 文件中的场景对象,也就是模型本身
            const model = gltf.scene;
            // 将模型添加到 three.js 的场景中
            scene.add(model);

            // 定义一个动画循环函数,用于不断更新和渲染场景
            const animate = () => {
                // 请求浏览器在下一次重绘之前调用 animate 函数,实现动画循环
                requestAnimationFrame(animate);
                // 渲染场景和相机,把 3D 场景变成我们能看到的画面
                renderer.render(scene, camera);
            };

            // 调用动画循环函数,开始动画
            animate();
        });

        // 设置相机的位置,让相机离场景有一定的距离,能看到整个场景
        camera.position.z = 5;

        // 组件卸载时的清理函数
        return () => {
            // 从 ref 对应的 DOM 元素中移除渲染器的 DOM 元素
            containerRef.current.removeChild(renderer.domElement);
        };
    }, []);

    // 返回一个 div 元素,用于承载 3D 场景
    return (
        <div ref={containerRef} />
    );
};

// 导出这个组件,方便其他地方使用
export default GLTFModelComponent;

在这个代码示例中,我们使用 React 和 Three.js 来加载一个 GLTF 格式的 3D 模型。首先创建了一个 3D 场景和相机,然后添加了灯光,接着使用 GLTFLoader 加载 GLTF 文件,最后把加载的模型添加到场景中并进行渲染。这样就能在网页上看到加载的 3D 模型啦。

如何将GLTF格式的模型导入到WebGL项目中?

如何将 GLTF 格式的模型导入到 WebGL 项目中

1. 准备工作

在把 GLTF 格式的模型导入到 WebGL 项目之前,你得先有一个 WebGL 项目的基础框架,这里我们用 three.js 这个库,它能让我们更轻松地操作 WebGL。另外,你得准备好一个 GLTF 格式的 3D 模型文件,就好比你要往房子里放一件家具,得先有房子和家具。

2. 安装依赖

如果你还没安装 three.js,可以用下面的命令来安装:

npm install three
3. 编写代码

下面是详细的代码示例,我会逐行加上注释,让你能看明白每一步是干啥的。

// 引入 React 的 useEffect 和 useRef 钩子,useEffect 用于处理副作用,useRef 用于创建一个可变的 ref 对象
import React, { useEffect, useRef } from'react';
// 引入 three.js 库,这是一个强大的 WebGL 抽象库,能让我们更方便地创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 模块,它专门用于加载 GLTF 格式的模型
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const GLTFModelComponent = () => {
    // 创建一个 ref 对象,用于引用后续要渲染 3D 场景的 DOM 元素
    const containerRef = useRef(null);

    useEffect(() => {
        // 创建一个新的 three.js 场景,这就像是一个舞台,所有的 3D 对象都会放在这个舞台上
        const scene = new THREE.Scene();
        // 创建一个透视相机,它决定了我们从哪个角度、多大范围去看这个 3D 场景
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 创建一个 WebGL 渲染器,它负责把 3D 场景渲染成我们能看到的画面
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染器的大小为浏览器窗口的宽度和高度,这样画面就能占满整个窗口
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 把渲染器生成的 DOM 元素添加到之前创建的 ref 对应的 DOM 元素中,这样渲染的画面就能显示在网页上了
        containerRef.current.appendChild(renderer.domElement);

        // 创建一个环境光,它会均匀地照亮整个场景,让场景不会太暗
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
        // 把环境光添加到场景中
        scene.add(ambientLight);

        // 创建一个点光源,它就像一个灯泡,能产生有方向的光照,让物体有明暗对比
        const pointLight = new THREE.PointLight(0xffffff, 1);
        // 设置点光源的位置
        pointLight.position.set(2, 5, 2);
        // 把点光源添加到场景中
        scene.add(pointLight);

        // 创建一个 GLTFLoader 实例,用于加载 GLTF 模型
        const loader = new GLTFLoader();

        // 调用 loader 的 load 方法来加载 GLTF 模型,这里的 'path/to/your/model.gltf' 要替换成你实际的模型文件路径
        loader.load('path/to/your/model.gltf', (gltf) => {
            // 当模型加载成功后,gltf.scene 就是加载好的 3D 模型对象
            const model = gltf.scene;
            // 把模型添加到场景中,这样模型就会出现在我们的舞台上了
            scene.add(model);

            // 定义一个动画函数,用于实现动画效果
            const animate = () => {
                // 请求浏览器在下一次重绘之前调用 animate 函数,实现动画循环
                requestAnimationFrame(animate);
                // 这里可以添加模型的动画逻辑,比如让模型旋转,下面的代码让模型绕 y 轴旋转
                model.rotation.y += 0.01;
                // 调用渲染器的 render 方法,把场景和相机作为参数传入,渲染出当前的画面
                renderer.render(scene, camera);
            };

            // 调用 animate 函数,开始动画循环
            animate();
        }, undefined, (error) => {
            // 如果加载模型过程中出现错误,打印错误信息
            console.error('加载模型时出错:', error);
        });

        // 设置相机的位置,让相机往后退一点,这样能看到整个场景
        camera.position.z = 5;

        // 组件卸载时的清理函数,移除渲染器的 DOM 元素,避免内存泄漏
        return () => {
            containerRef.current.removeChild(renderer.domElement);
        };
    }, []);

    return (
        // 创建一个 div 元素,用于容纳 3D 场景,通过 ref 属性关联到之前创建的 ref 对象
        <div ref={containerRef} />
    );
};

export default GLTFModelComponent;
4. 代码解释
  • 引入必要的库和模块three.js 是核心库,GLTFLoader 专门用来加载 GLTF 模型。
  • 创建场景、相机和渲染器:场景是 3D 对象的容器,相机决定了我们的视角,渲染器负责把场景渲染成画面。
  • 添加光照:环境光和点光源能让模型看起来更真实,有明暗对比。
  • 加载 GLTF 模型:使用 GLTFLoaderload 方法,传入模型文件路径,加载成功后把模型添加到场景中。
  • 实现动画:通过 requestAnimationFrame 实现动画循环,在循环中更新模型的状态,然后重新渲染画面。
  • 清理工作:组件卸载时,移除渲染器的 DOM 元素,避免内存泄漏。
5. 注意事项
  • 要把 'path/to/your/model.gltf' 替换成你实际的 GLTF 模型文件路径。
  • 如果模型文件有纹理等资源,要确保这些资源的路径也正确。

通过以上步骤,你就能把 GLTF 格式的模型导入到 WebGL 项目中,并且让它动起来啦!

常用的处理GLTF格式的JavaScript库

常用处理 GLTF 格式的 JavaScript 库介绍

在开发使用 GLTF 格式 3D 模型的网页应用时,有几个常用的 JavaScript 库能帮助我们轻松处理这些模型。下面详细介绍这些库以及给出使用示例。

1. three.js
  • 简介:three.js 是一个非常流行的 WebGL 抽象库,它把复杂的 WebGL 操作封装成简单的 API,让开发者能轻松创建和展示 3D 场景,同时也对 GLTF 格式有很好的支持。
  • 代码示例
// 引入 React 的 useEffect 和 useRef 钩子,用于在组件挂载和卸载时执行操作以及引用 DOM 元素
import React, { useEffect, useRef } from'react';
// 引入 three.js 库,用于创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 模块,专门用于加载 GLTF 格式的模型
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

const ThreeJSGLTFExample = () => {
    // 创建一个 ref 对象,用于引用存放 3D 场景的 DOM 元素
    const containerRef = useRef(null);

    useEffect(() => {
        // 创建一个 three.js 的场景对象,所有的 3D 元素都会添加到这个场景中
        const scene = new THREE.Scene();
        // 创建一个透视相机,设置视角、宽高比、近裁剪面和远裁剪面,模拟人眼的视角
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 创建一个 WebGL 渲染器,负责将 3D 场景渲染成 2D 图像显示在网页上
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染器的大小为窗口的宽度和高度
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 将渲染器的 DOM 元素添加到之前创建的 ref 对应的 DOM 元素中,这样就能在网页上显示场景了
        containerRef.current.appendChild(renderer.domElement);

        // 创建一个 GLTF 加载器实例
        const loader = new GLTFLoader();
        // 使用加载器加载指定路径的 GLTF 模型文件
        loader.load('path/to/your/model.gltf', (gltf) => {
            // 获取加载好的模型的场景对象
            const model = gltf.scene;
            // 将模型添加到之前创建的场景中
            scene.add(model);
        });

        // 设置相机的位置,让相机离场景有一定距离,能看到场景中的物体
        camera.position.z = 5;

        // 定义一个动画函数,用于不断更新和渲染场景
        const animate = () => {
            // 请求浏览器在下一次重绘之前调用 animate 函数,实现动画循环
            requestAnimationFrame(animate);
            // 使用渲染器渲染场景和相机,将 3D 场景转换成 2D 图像显示在网页上
            renderer.render(scene, camera);
        };

        // 调用动画函数,开始动画循环
        animate();

        // 组件卸载时的清理函数,移除渲染器的 DOM 元素,避免内存泄漏
        return () => {
            containerRef.current.removeChild(renderer.domElement);
        };
    }, []);

    return (
        // 创建一个 div 元素,用于存放 3D 场景,使用 ref 关联到之前创建的 ref 对象
        <div ref={containerRef} />
    );
};

export default ThreeJSGLTFExample;
2. Babylon.js
  • 简介:Babylon.js 是一个功能强大的 3D 游戏和场景开发引擎,它提供了丰富的工具和功能,能让开发者快速创建出高质量的 3D 应用,对 GLTF 格式的支持也很完善。
  • 代码示例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入 Babylon.js 的核心库 -->
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <!-- 引入 Babylon.js 的加载器扩展库,用于加载 GLTF 模型 -->
    <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
    <title>Babylon.js GLTF Example</title>
</head>

<body>
    <!-- 创建一个 canvas 元素,用于显示 3D 场景 -->
    <canvas id="renderCanvas"></canvas>
    <script>
        // 获取 canvas 元素
        const canvas = document.getElementById('renderCanvas');
        // 创建一个 Babylon.js 的引擎实例,负责管理渲染和更新逻辑
        const engine = new BABYLON.Engine(canvas, true);

        // 创建一个函数,用于创建 3D 场景
        const createScene = function () {
            // 创建一个新的场景对象
            const scene = new BABYLON.Scene(engine);
            // 创建一个自由相机,允许用户在场景中自由移动视角
            const camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene);
            // 设置相机看向场景的原点
            camera.setTarget(BABYLON.Vector3.Zero());
            // 让相机控制 canvas 的输入,比如鼠标和键盘操作
            camera.attachControl(canvas, true);

            // 创建一个半球光,照亮场景
            const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);
            // 设置光的强度
            light.intensity = 0.7;

            // 使用场景的加载器加载指定路径的 GLTF 模型文件
            BABYLON.SceneLoader.ImportMesh("", "path/to/your/", "model.gltf", scene, function (newMeshes) {
                // 当模型加载完成后,将第一个网格对象移动到指定位置
                newMeshes[0].position = new BABYLON.Vector3(0, 0, 0);
            });

            return scene;
        };

        // 调用创建场景的函数,得到场景对象
        const scene = createScene();

        // 监听引擎的渲染循环事件,不断更新和渲染场景
        engine.runRenderLoop(function () {
            scene.render();
        });

        // 监听窗口大小变化事件,当窗口大小改变时,调整渲染器的大小
        window.addEventListener('resize', function () {
            engine.resize();
        });
    </script>
</body>

</html>
3. PlayCanvas
  • 简介:PlayCanvas 是一个基于 WebGL 的开源游戏开发平台,它提供了直观的可视化编辑器和强大的 JavaScript API,对 GLTF 格式的模型加载和处理也很方便。
  • 代码示例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入 PlayCanvas 的引擎库 -->
    <script src="https://code.playcanvas.com/playcanvas-stable.min.js"></script>
    <title>PlayCanvas GLTF Example</title>
</head>

<body>
    <!-- 创建一个 canvas 元素,用于显示 3D 场景 -->
    <canvas id="application-canvas"></canvas>
    <script>
        // 获取 canvas 元素
        const canvas = document.getElementById('application-canvas');
        // 创建一个 PlayCanvas 的应用实例,传入 canvas 元素和配置对象
        const app = new pc.Application(canvas, {
            mouse: new pc.Mouse(canvas),
            touch: 'ontouchstart' in window? new pc.TouchDevice(canvas) : null
        });

        // 设置应用的分辨率为自动适应窗口大小
        app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
        app.setCanvasResolution(pc.RESOLUTION_AUTO);

        // 启动应用
        app.start();

        // 创建一个实体作为相机,设置其位置和旋转
        const camera = new pc.Entity('camera');
        camera.addComponent('camera', {
            clearColor: new pc.Color(0.1, 0.1, 0.1)
        });
        camera.setPosition(0, 0, 5);
        app.root.addChild(camera);

        // 创建一个实体作为光照,设置其类型和颜色
        const light = new pc.Entity('light');
        light.addComponent('light', {
            type: 'directional',
            color: new pc.Color(1, 1, 1),
            intensity: 1
        });
        light.setEulerAngles(45, 30, 0);
        app.root.addChild(light);

        // 创建一个资源加载器,用于加载 GLTF 模型
        const loader = new pc.AssetLoader();
        // 定义一个资源对象,指定资源的类型为 GLTF 模型
        const modelAsset = new pc.Asset('model', 'container', {
            url: 'path/to/your/model.gltf'
        });
        // 将资源添加到加载器中
        loader.add(modelAsset);

        // 加载资源
        loader.load(function (err, assets) {
            if (err) {
                console.error('加载模型出错:', err);
                return;
            }
            // 获取加载好的模型资源
            const model = modelAsset.resource.instantiateRenderEntity();
            // 将模型添加到场景的根实体中
            app.root.addChild(model);
        });
    </script>
</body>

</html>

这些库都能帮助你轻松处理 GLTF 格式的模型,你可以根据自己的项目需求选择合适的库。

GLTF格式和FBX格式有什么区别?

GLTF 格式和 FBX 格式的区别

1. 整体用途和定位
  • GLTF 格式:这是一种专门为网络传输设计的 3D 格式。就好比是为了在互联网上快速“快递”3D 模型而定制的包装。它的主要目标是让 3D 模型能在网页、游戏、虚拟现实(VR)和增强现实(AR)等场景里高效地加载和显示。
  • FBX 格式:它是一种通用的 3D 交换格式,就像一个大仓库,能把各种 3D 软件里创建的模型、动画、材质等信息都存起来,方便在不同的 3D 软件之间传递和使用。比如说,你在 Maya 里做了个模型,想拿到 3ds Max 里接着做,就可以用 FBX 格式来传输。
2. 文件结构和大小
  • GLTF 格式:它的文件结构比较简单,就像一个精简版的行李包。它把 3D 模型的信息分成几个部分,用 JSON 文件来描述模型的结构、材质、动画等,而模型的几何数据和纹理等可以单独存成二进制文件。这样一来,文件大小就比较小,在网络上传输起来就快多了。
  • FBX 格式:FBX 文件就像一个装满东西的大箱子,它把所有的信息都打包在一起,包括模型的几何形状、骨骼动画、材质纹理、光照信息等等。虽然信息很全面,但文件往往比较大,传输起来就没那么快。
3. 兼容性
  • GLTF 格式:在网络和现代 3D 引擎里的兼容性很好。很多流行的 3D 引擎,像 Three.js、Unity、Unreal Engine 等都对它有很好的支持。而且很多网页浏览器也能直接加载和显示 GLTF 模型,非常适合做网页 3D 展示。
  • FBX 格式:在专业的 3D 建模和动画软件里兼容性很强。像 Maya、3ds Max、Blender 等软件都能很好地导入和导出 FBX 文件。但在网页端的支持就相对没那么好,需要额外的处理才能在网页上显示。
4. 数据存储方式
  • GLTF 格式:它采用了一种分层的存储方式,就像把不同的东西放在不同的抽屉里。JSON 文件负责记录模型的整体结构和配置信息,而二进制文件专门存放模型的顶点数据、索引数据等。纹理文件也可以单独存储,这样可以根据需要灵活加载。
  • FBX 格式:是一种二进制的整体存储方式,就像把所有东西都混在一个大袋子里。虽然这样能保证数据的完整性,但在修改和提取特定数据时就比较麻烦。
5. 代码示例(使用 Three.js 加载 GLTF 和 FBX 模型)
// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';
// 引入 GLTFLoader 用于加载 GLTF 格式的 3D 模型
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
// 引入 FBXLoader 用于加载 FBX 格式的 3D 模型
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';

const ModelLoadingComponent = () => {
    // 创建一个 ref 用于引用存放 3D 场景的 DOM 元素
    const containerRef = useRef(null);

    useEffect(() => {
        // 创建 three.js 的场景
        const scene = new THREE.Scene();
        // 创建透视相机,设置视角、宽高比、近裁剪面和远裁剪面
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 创建 WebGL 渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染器的大小为窗口大小
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 将渲染器的 DOM 元素添加到 ref 对应的 DOM 元素中
        containerRef.current.appendChild(renderer.domElement);

        // 创建一个环境光,让场景整体更亮
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
        scene.add(ambientLight);

        // 创建一个点光源,让物体有明暗对比
        const pointLight = new THREE.PointLight(0xffffff, 1);
        pointLight.position.set(2, 5, 2);
        scene.add(pointLight);

        // 设置相机位置
        camera.position.z = 5;

        // 加载 GLTF 格式的模型
        const gltfLoader = new GLTFLoader();
        gltfLoader.load('path/to/your/model.gltf', (gltf) => {
            // 获取加载的模型
            const model = gltf.scene;
            // 将模型添加到场景中
            scene.add(model);
        });

        // 加载 FBX 格式的模型
        const fbxLoader = new FBXLoader();
        fbxLoader.load('path/to/your/model.fbx', (fbx) => {
            // 将加载的 FBX 模型添加到场景中
            scene.add(fbx);
        });

        // 定义渲染函数
        const animate = () => {
            // 请求下一帧动画
            requestAnimationFrame(animate);
            // 渲染场景
            renderer.render(scene, camera);
        };

        // 开始动画循环
        animate();

        // 组件卸载时清理资源
        return () => {
            containerRef.current.removeChild(renderer.domElement);
        };
    }, []);

    return (
        // 创建一个 div 用于存放 3D 场景
        <div ref={containerRef} />
    );
};

export default ModelLoadingComponent;

在这个代码示例里,我们用 Three.js 分别加载了 GLTF 和 FBX 格式的 3D 模型。通过对比加载过程和效果,能更直观地感受到这两种格式的特点。


http://www.kler.cn/a/578138.html

相关文章:

  • openharmory-鸿蒙生态设备之间文件互传发现、接入认证和文件传输
  • 用java如何利用jieba进行分词
  • STM32旋转编码器驱动详解:方向判断、卡死处理与代码分析 | 零基础入门STM32第四十八步
  • 算法系列之深度优先搜索寻找妖怪和尚过河问题的所有方式
  • 自执行函数(Self-Invoking Function)
  • Vue2使用jsts,将wkt转为geojson
  • 计算机网络篇:基础知识总结与基于长期主义的内容更新
  • 【问题解决】Jenkins使用File的exists()方法判断文件存在,一直提示不存在的问题
  • webshell一些上传心得
  • 代理IP与反爬技术的博弈
  • mysql经典试题共34题
  • UDP协议和报文格式
  • Redis | 哨兵 Sentinel
  • Java高频面试之集合-07
  • LeetCode 90: 子集 II
  • 【后端开发】go-zero微服务框架实践(goland框架对比,go-zero开发实践,文件上传问题优化等等)
  • Docker基础-项目部署流程解析
  • 07 HarmonyOS NEXT 仿uv-ui Tag组件开发教程系列(一)
  • VUE3开发-9、axios前后端跨域问题解决方案
  • K8s 1.27.1 实战系列(三)安装网络插件