提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
课程回顾:
如何在three.js 中引入不同的模型?
1. 格式 (不同的格式)
https://en.wikipedia.org/wiki/List_of_file_formats#3D_graphics // 请用外网打开
如果想要加载一个模型,必须根据不同的标准选择格式
OBJ FBX STL PLY 3DS GLTF
COLLADA
1.GLTF (使用这个) 会得到PBR材料 ,是基于物理的渲染材料,转化成网格标准材质
https://github.com/KhronosGroup/glTF-Sample-Models
// 将所需要的模型放到静态文件中,这取决与你要用什么
例如:static/models/Duck
这里有四个文件 对应格式 gltf ,gltf-binary(二进制),gltf-draco和gltf-embedded(嵌入式)
我们要知道怎么用,这些格式各有特点,取决于我们的需求,可以利用对方的特点和优势
2.如何在3D使用?
使用加载器 ,实时上我们之前使用了加载器,如:纹理加载器,字体加载器等
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js
gltfLoader.load()
将模型添加到场景中
scene.add(gltf.scene)
3.Draco压缩
Draco 比默认版本更加轻
压缩应用于缓冲数据,通常是几何体
Website: https://google.github.io/draco/
Git repository: https://github.com/google/draco
必须在GLTF之前实例化它
为什么更快?
draco压缩会将一部分js代码放到CPU上执行 使用WebAssembly和工人。
相当于两个线程一起工作
setDecoderPath
4.将DracoLoader实例给予glTFLoader加载器
setDRACOLoader
5. 什么时候使用draco版本
首先要DRACOLoader.js这个类,其次 在静态中把draco文件copy上去(解码器)
文件更大时候,更适合使用,这样压缩版本使用 文件更小,节约
6.冻结
若是一个巨大的几何体,使用WebAssembly和工人时候,会加载好几秒,也就是冻结
7.animations
如何处理动画
要播放动画需要 动画混合器
new THREE.AnimationMixer()
8.three.js3D编辑器
搜索three.js.edito,点击第一个 或者
https://threejs.org/editor/
在这个微型在线模型编辑器中,可以将模型文件拖到这里 快速查看模板是否符合自己需要
Duck.glb
一、代码
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import * as dat from 'lil-gui'
/**
* Base
*/
// Debug
const gui = new dat.GUI()
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
/*
Models
*/
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/draco/') // 要将models中的文件放到静态文件中 (注意要将数据放到models下)
const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)
let mixer = null
gltfLoader.load(
// '/models/Duck/glTF/Duck.gltf', // 2.
// '/models/FlightHelmet/glTF/FlightHelmet.gltf', // 会遇到将模型放到场景中,显示不全 1. 2.
// '/models/Duck/glTF-Draco/Duck.gltf', // draco 压缩 版本 2.
'/models/Fox/glTF/Fox.gltf', // 实现动画 会动的狐狸
(gltf)=>{
console.log(gltf)
// 这里注意若使用 for of 会造成循环混乱
// 1.初级使用, 让我们知道gltf 加载了什么,怎么加载
// 所以可以使用white 或者拓展运算符
// const children = [...gltf.scene.children]
// for(const child of children){
// scene.add(child)
// }
// 2.当然上面是为了理解,也可以一行代码搞定
// scene.add(gltf.scene)
// 3.实现狐狸动画
mixer = new THREE.AnimationMixer(gltf.scene) // 动画混合器
const action = mixer.clipAction(gltf.animations[2]) // 动画剪辑器 clipAction animations[0] 通过控制台可以看到狐狸关键帧数据,抬腿,摇头等等,
action.play() // 开始 同时需要在更新时间时候 更新关键帧
gltf.scene.scale.set(0.025,0.025,0.025)
scene.add(gltf.scene)
},
()=>{
console.log('progress')
},
()=>{
console.log('error')
}
)
/**
* Floor
*/
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(10, 10),
new THREE.MeshStandardMaterial({
color: '#444444',
metalness: 0,
roughness: 0.5
})
)
floor.receiveShadow = true
floor.rotation.x = - Math.PI * 0.5
scene.add(floor)
/**
* Lights
*/
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
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
// Updata mixer
if(mixer != null){
mixer.update(deltaTime)
}
// Update controls
controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
二、知识点
1.格式以及引用模型
OBJ FBX STL PLY 3DS GLTF
COLLADA
有不同的格式这里使用GLTF
GLTF
对应格式 gltf ,gltf-binary(二进制),gltf-draco和gltf-embedded(嵌入式)
如何使用
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js
gltfLoader.load()
将模型添加到场景中
scene.add(gltf.scene)
2.Draco压缩
如何使用
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/draco/') // 要将models中的文件放到静态文件中 (注意要将数据放到models下)
3.动画
new THREE.AnimationMixer() 动画混合器
clipAction 动画剪辑器
play 更新关键帧 同时要配合更新的时间使用
4.效果
1.鸭子关键代码 ,没有用到draco压缩
// models
const gltfLoader = new GLTFLoader()
gltfLoader.load(
'/models/Duck/glTF/Duck.gltf', // 2.
(gltf)=>{
console.log(gltf)
// const children = [...gltf.scene.children]
// for(const child of children){
// scene.add(child)
// }
scene.add(gltf.scene)
}
)
2.人像
const gltfLoader = new GLTFLoader()
// gltfLoader.setDRACOLoader(dracoLoader)
let mixer = null
gltfLoader.load(
// '/models/Duck/glTF/Duck.gltf', // 2.
'/models/FlightHelmet/glTF/FlightHelmet.gltf', // 会遇到将模型放到场景中,显示不全 1. 2.
(gltf)=>{
console.log(gltf)
// const children = [...gltf.scene.children]
for(const child of gltf.scene.children){
scene.add(child)
}
}
)
会看到加载进去的不完整
const gltfLoader = new GLTFLoader()
// gltfLoader.setDRACOLoader(dracoLoader)
gltfLoader.load(
// '/models/Duck/glTF/Duck.gltf', // 2.
'/models/FlightHelmet/glTF/FlightHelmet.gltf', // 会遇到将模型放到场景中,显示不全 1. 2.
(gltf)=>{
console.log(gltf)
const children = [...gltf.scene.children]
for(const child of children){
scene.add(child)
}
// scene.add(gltf.scene) //两种方式都可以
}
)
3.draco压缩使用 鸭子
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/draco/')
const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)
// let mixer = null
gltfLoader.load(
'/models/Duck/glTF-Draco/Duck.gltf', // draco 压缩 版本 2., // 会遇到将模型放到场景中,显示不全 1. 2.
(gltf)=>{
console.log(gltf)
// const children = [...gltf.scene.children]
// for(const child of children){
// scene.add(child)
// }
scene.add(gltf.scene)
}
)
4.狐狸
// models
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/draco/')
const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)
let mixer = null
gltfLoader.load(
// '/models/Duck/glTF/Duck.gltf', // 2.
// '/models/FlightHelmet/glTF/FlightHelmet.gltf', // 会遇到将模型放到场景中,显示不全 1. 2.
'/models/Fox/glTF/Fox.gltf', // 实现动画 会动的狐狸
(gltf)=>{
console.log(gltf)
mixer = new THREE.AnimationMixer(gltf.scene) // 动画混合器
const action = mixer.clipAction(gltf.animations[2]) // 动画剪辑器 clipAction animations[0] 通过控制台可以看到狐狸关键帧数据,抬腿,摇头等等,
action.play() // 开始 同时需要在更新时间时候 更新关键帧
gltf.scene.scale.set(0.025,0.025,0.025)
scene.add(gltf.scene)
}
)
注意更新时间
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
const deltaTime = elapsedTime - previousTime
previousTime = elapsedTime
// Updata mixer
if(mixer != null){
mixer.update(deltaTime)
}
// Update controls
controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
综合
效果
总结
无