赞
踩
- import './style.css'
- import * as THREE from 'three'
- import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
- import * as dat from 'dat.gui'
- import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader'
- import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
- /**
- * Base
- */
- // Debug
- const gui = new dat.GUI()
- const gltfLoader=new GLTFLoader()
- const dracoLoader=new DRACOLoader()
- dracoLoader.setDecoderPath('/draco/')
- // Canvas
- const canvas = document.querySelector('canvas.webgl')
- gltfLoader.setDRACOLoader(dracoLoader)
- // Scene
- const scene = new THREE.Scene()
- const floor=new THREE.Mesh(new THREE.PlaneBufferGeometry(10,10),new THREE.MeshStandardMaterial({
- metalness:0.4,
- roughness:0.5
- }))
- floor.rotation.x=-Math.PI*0.5
- scene.add(floor)
- /**
- * Lights
- */
- const ambientLight=new THREE.AmbientLight( 0x404040)
- scene.add(ambientLight)
- const directionalLight = new THREE.DirectionalLight(0xffffff, 0.6)
- directionalLight.castShadow = true
- directionalLight.shadow.mapSize.set(1024, 1024)
- directionalLight.shadow.camera.far = 15
- directionalLight.shadow.camera.left = - 7
- directionalLight.shadow.camera.top = 7
- directionalLight.shadow.camera.right = 7
- directionalLight.shadow.camera.bottom = - 7
- directionalLight.position.set(5, 5, 5)
- scene.add(directionalLight)
-
-
- /**
- * Sizes
- */
- const sizes = {
- width: window.innerWidth,
- height: window.innerHeight
- }
-
- window.addEventListener('resize', () =>
- {
- // Update sizes
- sizes.width = window.innerWidth
- sizes.height = window.innerHeight
-
- // Update camera
- camera.aspect = sizes.width / sizes.height
- camera.updateProjectionMatrix()
-
- // Update renderer
- renderer.setSize(sizes.width, sizes.height)
- renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
- })
-
- /**
- * Camera
- */
- // Base camera
- const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
- camera.position.set(2, 2, 2)
- scene.add(camera)
-
- // Controls
- const controls = new OrbitControls(camera, canvas)
- controls.target.set(0, 0.75, 0)
- controls.enableDamping = true
-
- /**
- * Renderer
- */
- const renderer = new THREE.WebGLRenderer({
- canvas: canvas
- })
- renderer.shadowMap.enabled = true
- renderer.shadowMap.type = THREE.PCFSoftShadowMap
- renderer.setSize(sizes.width, sizes.height)
- renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
-
- /**
- * Animate
- */
- const clock = new THREE.Clock()
- let previousTime = 0
-
- const tick = () =>
- {
- const elapsedTime = clock.getElapsedTime()
- const deltaTime = elapsedTime - previousTime
- previousTime = elapsedTime
- // Update controls
- controls.update()
-
- // Render
- renderer.render(scene, camera)
-
- // Call tick again on the next frame
- window.requestAnimationFrame(tick)
- }
-
- tick()
效果
用于载入glTF 2.0资源的加载器。
glTF(gl传输格式)是一种开放格式的规范 (open format specification), 用于更高效地传输、加载3D内容。该类文件以JSON(.glft)格式或二进制(.glb)格式提供, 外部文件存储贴图(.jpg、.png)和额外的二进制数据(.bin)。一个glTF组件可传输一个或多个场景, 包括网格、材质、贴图、蒙皮、骨架、变形目标、动画、灯光以及摄像机。
manager — 该加载器将要使用的 loadingManager 。默认为 THREE.DefaultLoadingManager。
创建一个新的GLTFLoader。
共有属性请参见其基类Loader。
共有方法请参见其基类Loader。
url — 包含有.gltf/.glb文件路径/URL的字符串。
onLoad — 加载成功完成后将会被调用的函数。该函数接收parse所返回的已加载的JSON响应。
onProgress — (可选)加载正在进行过程中会被调用的函数。其参数将会是XMLHttpRequest实例,包含有总字节数.total与已加载的字节数.loaded。
onError — (可选)若在加载过程发生错误,将被调用的函数。该函数接收error来作为参数。
开始从url加载,并使用解析过的响应内容调用回调函数。
- import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
- const gltfLoader=new GLTFLoader()
- const scene = new THREE.Scene()
- gltfLoader.load('models/Duck/glTF/Duck.gltf',(gltf)=>{
- console.log(gltf)
- })
效果
- import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
- const gltfLoader=new GLTFLoader()
- const scene = new THREE.Scene()
- gltfLoader.load('models/Duck/glTF/Duck.gltf',(gltf)=>{
- scene.add(gltf.scene.children[0])
- })
效果
如果我们像之前的一样引入则会只出现一个眼睛
所以我们需要加载全部的children
如果我们这么写
- gltfLoader.load('/models/FlightHelmet/glTF/FlightHelmet.gltf', gltf => {
- console.log(gltf)
- gltf.scene.children.forEach(element => {
- scene.add(element)
- });
- })
可以发现循环后的结果虽然可以看到有更多的模型元素,但一样不是完整的模型,而且更糟糕的是每当我们刷新页面,都会得到模型的不同部分。
问题出在于当我们把scene.children数组中的子元素从一个场景移到另一个场景的时候,它会自动从被移除的场景中删除掉,意味着我们循环的数组长度变小了。
当我们添加第一个对象时,它会从原来的场景中移除,然后第二个对象便会移动到替补上去。因此这里我们可以采用while循环来添加模型网格
- gltfLoader.load('/models/FlightHelmet/glTF/FlightHelmet.gltf', gltf => {
- while (gltf.scene.children.length) {
- scene.add(gltf.scene.children[0])
- }
- })
当然我们有最简单粗暴的方法 加载整个场景
- gltfLoader.load('/models/FlightHelmet/glTF/FlightHelmet.gltf', gltf => {
- scene.add(gltf.scene)
- })
- import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
-
- const dracoLoader=new DRACOLoader();
- dracoLoader.setDecoderPath('/draco/')
- gltfLoader.setDRACOLoader(dracoLoader)
-
- gltfLoader.load('/models/Duck/glTF-Draco/Duck.gltf', gltf => {
- const duck = gltf.scene.children[0]
- scene.add(duck)
- })
虽然我们可能会觉得使用Draco压缩是个双赢局面,但实际上并非如此。
确实它会让几何体更轻量,但首先要使用的时候必须加载DracoLoader类和解码器。其次,我们计算机解码一个压缩文件需要时间和资源,这可能会导致页面打开时有短暂冻结,即便我们使用了worker和WebAssembly。
因此我们必须根据实际来决定使用什么解决方案。如果一个模型具有100kb的几何体,那么则不需要Draco压缩,但是如果我们有MB大小的模型要加载,并且不关心在开始运行时有些许页面冻结,那么便可能需要用到Draco压缩。
1.初始化狐狸模型
- gltfLoader.load('/models/Fox/glTF/Fox.gltf', gltf => {
- const fox = gltf.scene
- fox.scale.set(0.025, 0.025, 0.025)
- scene.add(fox)
- })
- let mixer = null
-
- gltfLoader.load('/models/Fox/glTF/Fox.gltf', gltf => {
- // 创建混合器并传入gltf.scene
- mixer = new THREE.AnimationMixer(gltf.scene)
- // 使用clipAction()方法将索引为0的AnimationClip添加到混合器中
- // 这个方法会返回一个AnimationAction
- const action = mixer.clipAction(gltf.animations[0])
- // 使用play()方法调用这个AnimationAction
- action.play()
- gltf.scene.scale.set(0.025, 0.025, 0.025)
- scene.add(gltf.scene)
- })
在tick中更新动画
- const tick = () =>
- {
- const elapsedTime = clock.getElapsedTime()
- const deltaTime = elapsedTime - previousTime
- previousTime = elapsedTime
-
- if(mixer) {
- mixer.update(deltaTime)
- }
-
- // Update controls
- controls.update()
-
- // Render
- renderer.render(scene, camera)
-
- // Call tick again on the next frame
- window.requestAnimationFrame(tick)
- }
效果:
Three.js编辑器editor使用详解_zhr_superNiu的博客-CSDN博客_three.js编辑器
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。