3.js - 布尔动画(BooleanKeyframeTrack)

在这里插入图片描述

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秒时,在 000 这个位置
	  1秒时,在 200 这个位置
	  2秒时,在 400 这个位置
	  3秒时,在 200 这个位置
	  4秒时,在 000 这个位置
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的值
	    在这里,
	      轴向量是:(100),表示:绕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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值