import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.set(8, 2.5, 3)
camera.lookAt(0, 1.2, 0)
const renderer = new THREE.WebGLRenderer({
antialias: true
})
renderer.shadowMap.enabled = true
renderer.toneMapping = THREE.ReinhardToneMapping
renderer.toneMappingExposure = 1
// 画布的大小
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)
const gridHelper = new THREE.GridHelper(50, 50)
gridHelper.material.transparent = true
gridHelper.material.opacity = 0.3
scene.add(gridHelper)
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.dampingFactor = 0.01
// controls.autoRotate = true
// controls.autoRotateSpeed = 6
`THREE.Clock()`:Three.js中,测量时间,的工具类
`getDelta()`:返回,距离上次调用,getDelta(),以来经过的秒数
在渲染循环中,可以使用`clock.getDelta()`获取每帧之间的时间差,并据此更新动画和其他时间相关的状态。
let clock = new THREE.Clock()
`1- 创建 - 动画混合器`
let mixer, mixer_1
function render() {
controls.update()
let delta = clock.getDelta()
if (mixer) {
mixer.update(delta) `更新,动画混合器AnimationMixer中的动画动作actions的`
}
if(mixer_1){
mixer_1.update(delta) `更新,动画混合器AnimationMixer中的动画动作actions的`
}
requestAnimationFrame(render) // 在屏幕渲染下一帧画面时,触发回调函数,来执行画面的渲染
renderer.render(scene, camera)
}
render()
let rgbeLoader = new RGBELoader()
rgbeLoader.load('../public/assets/texture/Alex_Hart-Nature_Lab_Bones_2k.hdr', envMap => {
envMap.mapping = THREE.EquirectangularRefractionMapping
// scene.background = envMap
scene.background = new THREE.Color(0xcccccc)
scene.environment = envMap
})
const gltfLoader = new GLTFLoader()
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('../public/draco/')
gltfLoader.setDRACOLoader(dracoLoader)
// 户型基础模型
gltfLoader.load('../public/assets/model/house/house-scene-min.glb', gltf => {
basicScene = gltf.scene
})
// huawei.glb模型
gltfLoader.load('../public/assets/model/huawei.glb', gltf => {
huawei = gltf.scene
`创建 - 动画混合器`
// mixer = new THREE.AnimationMixer(huawei)
`获取动画`
在,加载gltf模型后,模型的数据(包括动画)会被存储在gltf对象中,
`gltf.animations是一个数组,包含了,模型中包含的所有动画剪辑`,
通过 `mixer.clipAction(gltf.animations[0])`,从该数组中,选择了第一个动画剪辑,
并且,为它创建了一个动画动作(action),
此时,这个动画动作,与`mixer`相关联,
但是,还没有开始播放
// const action = mixer.clipAction(gltf.animations[0])
`播放动画(默认情况:动画播放一次后停止)`
// action.play()
})
gltfLoader.load('../public/assets/model/moon.glb', gltf => {
console.log('gltf.scene', gltf.scene) // 拿到 gltf.scene 的 name,是:Sketchfab_Scene
scene.add(gltf.scene)
`布尔关键帧`
const boolKF = new THREE.BooleanKeyframeTrack(
'Sketchfab_Scene.visible',
[0, 1, 2, 3, 4],
[true, false, true, false, true]
)
`动画剪辑`
const clip = new THREE.AnimationClip('bool', 4, [boolKF])
`创建 - 动画混合器`
mixer_1 = new THREE.AnimationMixer(gltf.scene)
`将,动画混合器 与 动画剪辑,关联`
const action_1 = mixer_1.clipAction(clip)
action_1.play() // 播放
})
// -----------------------------------------------------------------------------------------------
let basicScene // 户型基础模型
let huawei // huawei.glb模型
let eventObj = {
addScene: () => scene.add(basicScene),
isLight: true, // 开关灯效果
addHuawei: () => scene.add(huawei)
}
const gui = new GUI()
gui.add(eventObj, 'addScene').name('添加户型基础模型')
gui
.add(eventObj, 'isLight')
.name('开关灯')
.onChange(value => {
if (value) {
renderer.toneMappingExposure = 1
} else {
renderer.toneMappingExposure = 0.1
}
})
gui.add(eventObj, 'addHuawei').name('添加huawei.glb模型')
// -----------------------------------------------------------------------------------------------
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshStandardMaterial({
color: 0xff33ff
})
const cube = new THREE.Mesh(geometry, material)
cube.name = 'cube'
scene.add(cube)
// -----------------------------------------------------------------------------------------------
`创建位移动画帧`
参数一:指向名为`cube`的对象的`position`属性
补充:这个参数,最好只是属性名(如:position),前提是:动画混合器已经正确的,绑定到目标对象上了
参数二:一个时间数组,表示,每个关键帧发生的时间(单位:秒)
在这里,动画将在0秒、1秒、2秒、3秒、4秒时,达到其关键帧
参数三:一个值数组,定义了,在每个关键帧时,对象位置的值,
因为,这是三维空间中的位置,
所以,每3个数字,表示一个点的位置,
说白了就是:
0秒时,在 0,0,0 这个位置
1秒时,在 2,0,0 这个位置
2秒时,在 4,0,0 这个位置
3秒时,在 2,0,0 这个位置
4秒时,在 0,0,0 这个位置
const positionKF = new THREE.VectorKeyframeTrack(
'cube.position',
[0, 1, 2, 3, 4],
[0, 0, 0,
2, 0, 0,
4, 0, 0,
2, 0, 0,
0, 0, 0]
)
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------
`创建 - 四元数对象`:
THREE.Quaternion():是一种用于表示3D空间中,旋转的数学结构,用于处理旋转的复杂运算;
`quaternion_1.setFromAxisAngle()`
基于,给定的轴向量,和,旋转角度,来设置四元数quaternion_1的值
在这里,
轴向量是:(1,0,0),表示:绕x轴旋转
旋转角度是:0弧度,即:不旋转
`quaternion_1.setFromEuler()`
使用setFromEuler(),基于给定的欧拉角(Euler angles),设置四元数`quaternion_1`的值,
在这里,
欧拉角为(0, 0, 0),表示:绕x、y、z轴,均不进行旋转
const quaternion_1 = new THREE.Quaternion()
// quaternion_1.setFromAxisAngle(new THREE.Vector3(1, 0, 0), 0)
quaternion_1.setFromEuler(new THREE.Euler(0, 0, 0))
const quaternion_2 = new THREE.Quaternion()
// quaternion_2.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI)
quaternion_2.setFromEuler(new THREE.Euler(Math.PI, 0, 0))
const quaternion_3 = new THREE.Quaternion()
// quaternion_3.setFromAxisAngle(new THREE.Vector3(1, 0, 0), 0)
quaternion_3.setFromEuler(new THREE.Euler(0, 0, 0))
const finQ = quaternion_1.toArray()
.concat(quaternion_2.toArray())
.concat(quaternion_3.toArray())
`创建 - 旋转动画帧`
const rotationKF = new THREE.QuaternionKeyframeTrack('cube.quaternion', [0, 2, 4], finQ)
// -----------------------------------------------------------------------------------------------
// 创建 - 布尔动画帧
const boolKF = new THREE.BooleanKeyframeTrack('cube.visible', [0, 1, 2, 3, 4], [true, false, true, false, true])
// -----------------------------------------------------------------------------------------------
`2-创建 - 动画剪辑`
参数一:动画剪辑的名称
参数二:动画的持续时间(单位:秒),与关键帧时间数组中的最后一个时间值相匹配
参数三:包含关键帧轨迹的数组,
这里,它只包含一个关键帧轨迹,即:`positionKF`,它定义了对象位置随时间的变化
const clip = new THREE.AnimationClip('move', 4, [positionKF, rotationKF, boolKF])
`3-创建 - 动画混合器`
mixer = new THREE.AnimationMixer(cube)
`4-创建动画动作`(将动画混合器 与 动画剪辑 关联起来)
const action = mixer.clipAction(clip)
action.play()
3.js - 布尔动画(BooleanKeyframeTrack)
于 2024-07-29 15:50:24 首次发布