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

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

大白话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 模型。通过对比加载过程和效果,能更直观地感受到这两种格式的特点。

相关文章:

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

大白话react第十八章React 与 WebGL 项目的高级拓展与优化 1. 实现 3D 模型的导入与动画 在之前的基础上&#xff0c;我们可以导入更复杂的 3D 模型&#xff0c;并且让这些模型动起来&#xff0c;就像在游戏里看到的角色和场景一样。这里我们使用 GLTF 格式的模型&#xff0c…...

【WPF】Slider滑动方法(INotifyPropertyChanged、ValueChanged )响应速度对比分析

一、Slider基础用法 在 XAML 中添加一个 Slider 控件&#xff0c;并设置其基本属性&#xff1a; <Slider Minimum"0" <!-- 最小值 -->Maximum"100" <!-- 最大值 -->Value"50" <!-- 初始值 -->Width&quo…...

DeepSeek未来发展趋势:开创智能时代的新风口

DeepSeek未来发展趋势&#xff1a;开创智能时代的新风口 随着人工智能&#xff08;AI&#xff09;、深度学习&#xff08;DL&#xff09;和大数据的飞速发展&#xff0c;众多创新型技术已经逐渐走向成熟&#xff0c;而DeepSeek作为这一领域的新兴力量&#xff0c;正逐步吸引越…...

1-003:MySQL 的索引类型有哪些?

MySQL 中的索引类型主要分为以下几类&#xff0c;每种索引都有不同的适用场景和优化查询的作用&#xff1a; 1. 按存储结构分类 ① 聚簇索引&#xff08;Clustered Index&#xff09; 特点&#xff1a; InnoDB 引擎的 主键索引 就是 聚簇索引。数据与索引存储在一起&#xff…...

从0开始的操作系统手搓教程24——完成我们的键盘驱动子系统

目录 所以&#xff0c;我们现来说说转义字符 我们需要如何处理扫描码 当键入的是双字符键时 当键入的是字母键时 下一篇 我们下面来看看我们的键盘驱动子系统是一个怎么个事情。 驱动程序&#xff0c;你可以认为是对硬件的一层封装。我们按照手册规格的规定姿势&#xff0…...

git大文件传输报错

简述 git传输大于25M的文件时会报错&#xff0c;需要使用 Git LFS进行文件传输。 Git LFS&#xff08;Large File Storage&#xff09;是 GitHub 推荐的方式&#xff0c;可以管理大文件而不会影响 Git 性能。 操作流程 # 安装 Git LFS git lfs install# 将 PDF 文件添加到 G…...

基础玩转物联网-4G模块如何快速实现与MQTT服务器通信

目录 1 前言 2 环境搭建 2.1 硬件准备 2.2 软件准备 2.3 硬件连接 2.4 检查驱动 3 连接MQTT服务器 3.1 创建MQTT监听Topic 3.2 打开配置工具读取基本信息 3.3 设置连接参数进行数据交互 4 总结 1 前言 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻…...

使用Beanshell前置处理器对Jmeter的请求body进行加密

这里我们用HmacSHA256来进行加密举例&#xff1a; 步骤&#xff1a; 1.先获取请求参数并对请求参数进行处理&#xff08;处理成String类型&#xff09; //处理请求参数的两种方法&#xff1a; //方法一&#xff1a; //获取请求 Arguments args sampler.getArguments(); //转…...

Python入门3:类与面对对象

目录 类 一、类的概念 二、类的定义和使用 2.1 类的定义 2.2 实例化对象 三、类的属性和方法 3.1 属性 属性的类型&#xff1a; 补充--私有属性 属性的操作&#xff1a; 3.2 方法 方法的类型&#xff1a; 补充--私有方法 方法的操作 四、面对过程和面对对象 …...

mac本地部署Qwq-32b记录

导语 昨天看到阿里开源了Qwq-32b&#xff0c;号称性能可以媲美Deepseek-R1。今天晚上有空就在Mac上折腾了一下&#xff0c;使用ollma进行了部署&#xff0c;效果感觉还不错&#xff0c;特此记录。 环境 硬件 型号&#xff1a;Macbook M1 Pro 14寸内存&#xff1a;512G 环境…...

【病毒分析】熊猫烧香病毒分析及其查杀修复

目录 前言 一、样本概况 1.1 样本信息 1.2 测试环境及工具 1.3 分析目标 二、具体行为分析 2.1 主要行为 2.1.1 恶意程序对用户造成的危害 2.2 恶意代码分析 2.2.1 加固后的恶意代码树结构图(是否有加固) 2.2.2 恶意程序的代码分析片段 三、解决方案(或总结) 3.1 …...

【语料数据爬虫】Python实现将Json语料数据转换成Word文档

前言 本文是该专栏的第1篇,后面会持续分享Python爬虫采集各种语料数据的的干货知识,值得关注。 本专栏为笔者精心推出的“语料数据”爬虫专栏,特别适合需要写作素材的同学,该专栏文章以采集最新的“语料数据”为主,最终篇幅将涵盖【百万级语料数据】库。 值得一提的是,…...

警惕AI神话破灭:深度解析大模型缺陷与禁用场景指南

摘要 当前AI大模型虽展现强大能力&#xff0c;但其本质缺陷可能引发系统性风险。本文从认知鸿沟、数据困境、伦理雷区、技术瓶颈四大维度剖析大模型局限性&#xff0c;揭示医疗诊断、法律决策等8类禁用场景&#xff0c;提出可信AI建设框架与用户防护策略。通过理论分析与实操案…...

做到哪一步才算精通SQL

做到哪一步才算精通SQL-Structured Query Language 数据定义语言 DDL for StructCREATE&#xff1a;用来创建数据库、表、索引等对象ALTER&#xff1a;用来修改已存在的数据库对象DROP&#xff1a;用来删除整个数据库或者数据库中的表TRUNCATE&#xff1a;用来删除表中所有的行…...

leetcode454 四数相加

四数相加Ⅱ的解法可以将四数分为两组&#xff0c;即“分组 哈希”&#xff1a; 初始化哈希表。 分组&#xff1a;nums1 和 nums2 一组&#xff0c;nums3 和 nums4 一组。 分别对 nums1 和 nums2 进行遍历&#xff0c;将所有 nums1 和 nums2 的值的和作为哈希表的 key&#x…...

RoboVQA:机器人多模态长范围推理

23 年 11 月来自 Google Deepmind 的论文“RoboVQA: Multimodal Long-Horizon Reasoning for Robotics”。 本文提出一种可扩展、自下而上且本质多样化的数据收集方案&#xff0c;该方案可用于长期和中期的高级推理&#xff0c;与传统的狭窄自上而下的逐步收集相比&#xff0c…...

C 语言数据结构(二):顺序表和链表

目录 1. 线性表 2. 顺序表 2.1 概念及结构 2.1.1 静态顺序表&#xff08;不常用&#xff09; 2.1.2 动态顺序表&#xff08;常用&#xff09; ​编辑 2.2 练习 2.2.1 移除元素 2.2.2 删除有序数组中的重复项 2.2.3 合并两个有序数组 2.3 顺序表存在的问题 3. 链表 …...

无公网IP也能远程控制Windows:Linux rdesktop内网穿透实战

文章目录 前言1. Windows 开启远程桌面2. Linux安装rdesktop工具3. Win安装Cpolar工具4. 配置远程桌面地址5. 远程桌面连接测试6. 设置固定远程地址7. 固定地址连接测试 前言 如今远程办公已经从一种选择变成了许多企业和个人的必修课&#xff0c;而如何在Linux系统上高效地访…...

uniapp+Vue3 开发小程序的下载文件功能

小程序下载文件&#xff0c;可以先预览文件内容&#xff0c;然后在手机上打开文件的工具中选择保存。 简单示例&#xff1a;&#xff08;复制到HBuilder直接食用即可&#xff09; <template><view class"container-detail"><view class"example…...

blazemeter工具使用--用于自动生成jmeter脚本并进行性能测试

1、安装blazemeter&#xff08;网上有很多详情的教程&#xff09; 2、开始录制&#xff1a;设置号你的文件名称后开始录制 3、录制完成后保存为jmeter(jmx)文件 4、在jmeter中打开文件 5、添加一个后置处理器&#xff1a;查看结果树&#xff0c;后运行看看能否成功&#xf…...

【实战ES】实战 Elasticsearch:快速上手与深度实践-7.2.2自动扩缩容策略(基于HPA)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 7.2.2 基于HPA的Elasticsearch自动扩缩容深度实践1. 云原生时代弹性伸缩的核心价值1.1 业务负载特征分析1.2 传统扩缩容方式的局限性 2. HPA核心机制深度解析2.1 HPA工作原理…...

通义万相2.1:开启视频生成新时代

文章摘要&#xff1a;通义万相 2.1 是一款在人工智能视频生成领域具有里程碑意义的工具&#xff0c;它通过核心技术的升级和创新&#xff0c;为创作者提供了更强大、更智能的创作能力。本文详细介绍了通义万相 2.1 的背景、核心技术、功能特性、性能评测、用户反馈以及应用场景…...

如何用HTML5 Canvas实现电子签名功能✍️

&#x1f916; 作者简介&#xff1a;水煮白菜王&#xff0c;一位资深前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 前端专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧和知识归纳总结✍。 感谢支持&#x1f495;&#x1f495;&a…...

区块链中的数字签名:安全性与可信度的核心

数字签名是区块链技术的信任基石&#xff0c;它像区块链世界的身份证和防伪标签&#xff0c;确保每一笔交易的真实性、完整性和不可抵赖性。本文会用通俗的语言&#xff0c;带你彻底搞懂区块链中的数字签名&#xff01; 文章目录 1. 数字签名是什么&#xff1f;从现实世界到区块…...

RabbitMQ 高级特性:从 TTL 到消息分发的全面解析 (下)

RabbitMQ高级特性 RabbitMQ 高级特性解析&#xff1a;RabbitMQ 消息可靠性保障 &#xff08;上&#xff09;-CSDN博客 RabbitMQ 高级特性&#xff1a;从 TTL 到消息分发的全面解析 &#xff08;下&#xff09;-CSDN博客 引言 RabbitMQ 作为一款强大的消息队列中间件&#xff…...

表格columns拼接两个后端返回的字段(以umi框架为例)

在用组件对前端项目进行开发时&#xff0c;我们会遇到以下情况&#xff1a;项目原型中有取值范围这个表字段&#xff0c;需要存放最小取值到最大取值。 而后端返回给我们的数据是返回了一个最小值和一个最大值&#xff0c; 在columns中我们需要对这两个字段进行拼接&#xff0…...

sparkTTS window 安装

SparkTTS 的简介 Spark-TTS是一种基于SpardAudio团队提出的 BiCodec 构建的新系统&#xff0c;BiCodec 是一种单流语音编解码器&#xff0c;可将语音策略性地分解为两种互补的标记类型&#xff1a;用于语言内容的低比特率语义标记和用于说话者特定属性的固定长度全局标记。这种…...

【K8S系列】深入探究Kubernetes中查看日志的方法

在Kubernetes&#xff08;简称K8s&#xff09;的世界里&#xff0c;日志是诊断和排查问题的关键线索。无论是应用程序的运行状态、错误信息&#xff0c;还是系统的健康状况&#xff0c;都能从日志中找到蛛丝马迹。本文将详细介绍在K8s中查看日志的各种方法&#xff0c;从基础的…...

How to install nodejs with nvm on Linux mint 22.1

nvm是nodejs官方用于管理nodejs多版本环境的一个工具 &#xff0c;今天&#xff0c;我带领大家基于nvm完成nodejs在Linux mint 22.1上的安装。 考虑到Linux mint 22.1是基于ubuntu 24.04.1 LTS的&#xff0c;所以&#xff0c;这里的安装也完全适用于nodejs在nodejs上的安装。 …...

JmeterHttp请求头管理出现Unsupported Media Type问题解决

JmeterHttp请求头管理出现Unsupported Media Type问题解决 大多数的app与pc端压测的时候都会出现这种情况 当我们在jemter测试当中当中遇见Unsupported Media Type&#xff0c;有一种可能就是我们请求的网页的content-Type的类型与我们测试的时候的类型不一致 解决方法 可以添…...