VUE2+THREE.JS 按照行动轨迹移动人物模型并相机视角跟随人物

这篇具有很好参考价值的文章主要介绍了VUE2+THREE.JS 按照行动轨迹移动人物模型并相机视角跟随人物。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

人物按照上一篇博客所设定的关键点位置,匀速移动

threejs 人物移动,ThreeJS,VUE,javascript,数码相机,开发语言

1. 初始化加载模型

// 加载巡航人物模型 callback 动作完成的回调函数
initWalkPerson(callback) {
	fbxloader("walk").then((obj) => {
		obj.scale.set(2.5, 2.5, 2.5);
		obj.name = "person";
		person = obj;
		scene.add(obj);
		//有回调函数 就执行回调函数
		callback && callback();
	});
},

2. 开始移动模型

// 开始移动模型
startAnimation() {
	if (isAnimating) return this.elMessage("当前巡航已开始,请勿多次操作", "error");
	isAnimating = true;
	//说明模型已加载完成,无需重复加载,直接执行动画效果
	if (person) {
		this.personPositionStart();
	} else {
		//人物模型加载完毕后在执行
		this.initWalkPerson(() => {
			this.personPositionStart();
		});
	}
},

3. 人物模型启动

//人物动画启动
personPositionStart() {
	personMixer = new THREE.AnimationMixer(person);
	let AnimationAction = personMixer.clipAction(person.animations[0]);
	AnimationAction.play();

	person.position.set(pointArr[0]);
	scene.getObjectByName("path").material.visible = false; //隐藏行动轨迹动画
	scene.getObjectByName("person").visible = true;

	tweenHandlers = [];
	// 定义速度(单位:单位长度/秒)
	const speed = 300; // 你可以根据需要调整这个速度值
	let prevTween = null;
	let startPos = new THREE.Vector3(...pointArr[0]);

	for (let i = 1; i < pointArr.length; i++) {
		// 每次循环设置下一个目标点
		const endPos = new THREE.Vector3(...pointArr[i]);
		const newTween = this.createTween(startPos.clone(), endPos, speed);
		tweenHandlers.push(newTween);

		if (prevTween) {
			prevTween.chain(newTween);
		} else {
			// 如果是序列中的第一个tween,立即开始动画
			newTween.start();
		}

		// 将此tween存储为下一个tween的'prevTween'
		prevTween = newTween;

		// 更新起始点为当前结束点,为下一个循环准备
		startPos.copy(endPos);
	}

	// 开始第一个tween动画
	if (tweenHandlers.length > 0) {
		currentTween = tweenHandlers[0];
		currentTween.start();
		isAnimating = true;
	}
	// 在最后一个Tween结束后执行的动作
	prevTween.onComplete(() => {
		// 在动画被标记为完成时才重置位置
		this.resetPosition();
	});
},

4. 暂停模型移动

// 暂停模型移动
pauseAnimation() {
	if (!isAnimating) {
		this.elMessage("当前巡航未开始", "warning");
		return;
	}

	if (this.isPaused) {
		// 恢复摄像机状态
		camera.position.copy(savedCameraPosition);
		controls.target.copy(savedCameraTarget);
		controls.update();

		// 恢复动画
		tweenHandlers.forEach((tween) => tween.resume());
		personMixer.timeScale = 1;
		this.isPaused = false; //设置this.isPaused为false
		isAnimating = true;
		this.elMessage("动画已恢复", "success");

		this.updateCameraPosition(person, camera, new THREE.Vector3(0, 250, 200));
	} else {
		// 保存当前摄像机状态
		savedCameraPosition = camera.position.clone();
		savedCameraTarget = controls.target.clone();
		// 暂停动画
		tweenHandlers.forEach((tween) => tween.pause());
		personMixer.timeScale = 0;
		this.isPaused = true; //设置this.isPaused为true
		this.elMessage("动画已暂停", "success");
	}
},

5. 重置模型位置

// 重置模型位置
resetPosition() {
	isAnimating = false;
	this.pauseAnimation();
	// 将模型从场景中移除
	scene.getObjectByName("person").visible = false;
	// 清理动画混合器
	if (personMixer) {
		personMixer.uncacheClip(personMixer._actions[0]._clip);
		personMixer = null;
	}
	tweenHandlers.forEach((item) => item.stop());
	tweenHandlers = [];
	// 重置动画状态
	this.isPaused = false;
	this.tweenArea({ x: -5000, y: 7000, z: 16000 }, { x: 0, y: 0, z: 1 });
	//显示行动轨迹
	scene.getObjectByName("path").material.visible = true;
},

6. 切换区域动画

// 切换区域动画
tweenArea(Position, controlsTarget) {
	// 传递任意目标位置,从当前位置运动到目标位置
	const p1 = {
		// 定义相机位置是目标位置到中心点距离的2.2倍
		x: camera.position.x,
		y: camera.position.y,
		z: camera.position.z,
	};
	const p2 = {
		x: Position.x,
		y: Position.y,
		z: Position.z,
	};
	changeAreaTween = new TWEEN.Tween(p1).to(p2, 1200); // 第一段动画
	const update = function (object) {
		camera.rotation.y = (90 * Math.PI) / 180;
		camera.position.set(object.x, object.y, object.z);
		controls.target = new THREE.Vector3(controlsTarget.x, controlsTarget.y, controlsTarget.z);
		// camera.lookAt(lookAt); // 保证动画执行时,相机焦距在中心点
		controls.enabled = false;
		controls.update();
	};
	changeAreaTween.onUpdate(update);
	//  动画完成后的执行函数
	changeAreaTween.onComplete(() => {
		controls.enabled = true; // 执行完成后开启控制
	});
	changeAreaTween.easing(TWEEN.Easing.Quadratic.InOut);
	changeAreaTween.start();
},

7. 摄像机追踪模型

// 摄像机追踪模型
updateCameraPosition(model, camera, offset) {
	if (!this.isPaused && isAnimating) {
		// 添加条件判断
		const desiredPosition = new THREE.Vector3().copy(model.position).add(offset);

		camera.position.lerp(desiredPosition, 0.05);
		camera.lookAt(model.position);
	}
},

8. 移动模型位置

// 移动模型位置
createTween(startPosition, endPosition, speed) {
	// 计算起点到终点的距离
	const distance = startPosition.distanceTo(endPosition);
	// 使用距离除以速度来计算持续时间
	const duration = (distance / speed) * 1000; // 持续时间(以毫秒为单位)
	// 创建并返回一个新的Tween动画
	return new TWEEN.Tween(startPosition)
		.to({ x: endPosition.x, y: endPosition.y, z: endPosition.z }, duration)
		.easing(TWEEN.Easing.Quadratic.InOut)
		.onUpdate(() => {
			//相机的相对偏移量,z=-400 在人物模型的后面
			const relativeCameraOffset = new THREE.Vector3(0, 100, -400);
			const targetCameraPosition = relativeCameraOffset.applyMatrix4(person.matrixWorld);
			camera.position.set(targetCameraPosition.x, targetCameraPosition.y, targetCameraPosition.z);

			//更新控制器的目标为Person的位置
			const walkerPosition = person.position.clone();
			controls.target = new THREE.Vector3(walkerPosition.x, 100, walkerPosition.z);
			// 确保控制器的变更生效
			controls.update();

			// 更新模型位置
			person.position.copy(startPosition);
			person.lookAt(endPosition);
		})
		.onComplete(() => {
			// 动画完成时,确保模型位置与结束位置相匹配
			person.position.copy(endPosition);
		});
},

9.动画执行

全局定义的参数:文章来源地址https://www.toymoban.com/news/detail-830832.html

let personMixer = null; // 巡航混合器变量
let personClock = new THREE.Clock(); // 巡航计时工具
// 获取巡航时间差
const personDelta = personClock.getDelta();

if (personMixer && isAnimating) {
	personMixer.update(personDelta);
}
TWEEN.update();

到了这里,关于VUE2+THREE.JS 按照行动轨迹移动人物模型并相机视角跟随人物的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue2+three.js实现类似VR、3D全景效果

    效果图: 俩图标是我自己加的前进后退按钮,也是百度了好久,再加上GPT的帮助,才给搞出来。因为需求急,都不看官方文档,百度到一个能跑的demo之后改吧改吧,就先用着了。 下面是代码: 这里 代码有很多用不到的地方和需要优化的地方,我是来不及改了,就先这样吧

    2024年02月15日
    浏览(54)
  • Three.js - 通过键盘控制模型移动和攻击(二十五)

    上节加载了模型和模型动画,本节使用键盘控制模型移动和连贯动画实现攻击动作。 基础模板 上节讲述加载了模型,并实现了动画。本节在上节的基础上进行修改。 修改灯光并添加阴影 开启阴影渲染。 添加方向光,开启阴影投射。 在地面网格上开启阴影接收。 修改模型网

    2024年02月10日
    浏览(55)
  • Three.js中光线投射Raycaster的简单使用案例 与模型的交互,当鼠标移动到模型时出现信息框

    目录 说明   创建两个模型 基础代码  基础代码效果图如下: 重点!!!   创建光线投射Raycaster实例步骤 1.准备一个盒子,用来展示模型的长宽高信息,初始化时先隐藏该盒子 2.创建光线投射Raycaster实例         1.创建 Raycaster 实例            2.为窗口绑定事件 p

    2024年02月05日
    浏览(47)
  • vue2 使用 cesium 【第二篇-相机视角移动+添加模型】

    搞了一阵子 cesium,小白入门,这东西很牛逼,但是感觉这东西好费劲啊!网上资料不多,每个人的用法又不一样,操作起来真的是绝绝子。之前写了一篇 vue2 使用 cesium 的博文,没有写完,本来想继续写来着,想了一下还是重新开一篇吧。上一篇说到了事件,今天不想写事件

    2024年02月11日
    浏览(47)
  • 【Vue】Vue2创建移动端项目实战教程,创建移动端项目保姆级教程,设置axios,utils工具包,vue.fonfig.js配置项 (下)

    这里是创建移动端项目 【Vue】Vue2.x创建项目全程讲解,保姆级教程,手把手教,Vue2怎么创建项目(上) 【Vue】Vue2创建移动端项目实战教程,创建移动端项目保姆级教程,接上一篇创建Vue2项目(中) 【Vue】Vue2创建移动端项目实战教程,创建移动端项目保姆级教程,设置ax

    2024年02月13日
    浏览(53)
  • Three.js -相机平滑移动

    一、安装 二、引入 三、使用 最后不要忘了在render中执行 TWEEN.update();

    2024年02月13日
    浏览(61)
  • Unity Animator人物模型动画移动偏移

    模型动画出现移动方向偏移 !修改Animation中的Root Transform Rotation(根变换位置)、Root Transform Rotation(x,y,z)(旋转),Bake Info Pose修改为Original。可以解决 !!但是,使用动画移动函数时将无法移动,原因是锁定根变换位置和循环位置 !!!所以只要修改依据为原始或者微调偏离值,

    2024年02月15日
    浏览(43)
  • Three 之 three.js (webgl)鼠标/手指通过射线移动物体的简单整理封装

    目录 Three 之 three.js (webgl)鼠标/手指通过射线移动物体的简单整理封装 一、简单介绍 二、实现原理 三、注意事项 四、效果预览 五、案例实现步骤 六、关键代码 Three js 开发的一些知识整理,方便后期遇到类似的问题,能够及时查阅使用。 本节介绍, three.js (webgl) 中,

    2024年02月16日
    浏览(61)
  • three.js实现鼠标点击控制物体移动(带动画效果,位置精确)

    通过查阅各种资料,最终确定解决方案,动画效果使用gsap组件库实现,也可不用,代码稍作修改即可。解决鼠标点击坐标偏移问题,复制可直接运行。 完整代码如下:

    2024年02月07日
    浏览(60)
  • Three.js移动端双指触屏控制旋转和缩放

    在移动端通过双指来控制物体的选择和缩放。旋转通过双指旋转操作,而缩放通过双指距离实现。实现平台是小程序基于three.js的AR版。 旋转:两个手指产生的两个点可以算出一个向量,那么我就通过程序前后两帧计算两个向量之间的夹角来判断旋转的角度信息。这里我通过

    2024年02月08日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包