123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- import settings from "./utils/settings.js"
- export default class Charactor {
- constructor(newMeshes, particleSystems, skeletons, animationGroups) {
- this.mesh = newMeshes[0]
- this.particleSystem = particleSystems[0]
- this.skeleton = skeletons[0]
- this.modelData = { newMeshes, particleSystems, skeletons, animationGroups }
- // 设置人物动画权重
- this.animation = {}
- animationGroups.forEach((ani, index) => {
- this.animation[ani.name] = ani
- ani.play(true)
- if(index == 0) {
- ani.setWeightForAllAnimatables(1);
- this.actionType = ani.name + "-" + ani.name
- }
- else ani.setWeightForAllAnimatables(0);
- })
- // 动画沙漏, 用于人物模型动画权重转换
- this.aniHourglass = {
- upper: 0,
- lower: 1,
- }
- // 人物行走数据,通过startWalk更新
- this.walkData = {
- pathArr: [],
- currentPoint: 0
- }
- }
- set visible(isVisible) {
- this.modelData.newMeshes.forEach(mesh => mesh.isVisible = isVisible)
- }
- get visible() {
- return this.mesh.isVisible
- }
- updateAniTrans() {
- // 实时更新角色模型动画
- if(this.aniHourglass.upper > 0) {
- // 10帧动画过渡
- this.aniHourglass.upper = (this.aniHourglass.upper * 10 - 1) / 10
- this.aniHourglass.lower = (this.aniHourglass.lower * 10 + 1) / 10
- let fromAni = this.actionType.split("-")[0]
- let toAni = this.actionType.split("-")[1]
- this.animation[fromAni].setWeightForAllAnimatables(this.aniHourglass.upper);
- this.animation[toAni].setWeightForAllAnimatables(this.aniHourglass.lower);
- }
- }
- AniTransfromTo(aniName) {
- let lastAniName = this.actionType.split("-")[1]
- if(lastAniName == aniName) return
- // 颠倒沙漏
- this.aniHourglass = {
- upper: 1,
- lower: 0,
- }
- this.actionType = lastAniName + "-" + aniName
- }
- startWalk(pathArr, charactorManager) {
- this.walkData = {
- pathArr: pathArr,
- currentPoint: -1
- }
-
- if(pathArr.length >= 2 && this.actionType.split("-")[1] != "Walking")
- {
- this.walkData.currentPoint = 0
- let video = pathArr[0].video
- if(video.isLoaded) {
- this.AniTransfromTo("Walking")
- this.walkByPath(charactorManager)
- } else {
- video.onloadeddata = () => {
- this.AniTransfromTo("Walking")
- this.walkByPath(charactorManager)
- }
- }
- }
- }
-
- walkByPath(charactorManager) {
- let charactor = this
- let { pathArr, currentPoint } = charactor.walkData
- // 更新房间的视频贴图
- let video = pathArr[currentPoint].video
- charactorManager.app.updateHouseVideo(video)
- let nextPos = pathArr[currentPoint+1].point
- // console.error(pathArr, video)
- // 立即获取下一个点的旋转视频,防止中途旋转导致行走停止
- let endPointId = pathArr[currentPoint+1].id
- console.log("[3D] send(getRotateVideoUrl): ", endPointId + "/" + endPointId)
- window.connection.socket.emit("getRotateVideoUrl", {
- videoPath: endPointId + "/" + endPointId,
- sceneCode: settings.sceneCode,
- roomId: settings.roomId,
- userId: settings.userId,
- });
- window.connection.socket.emit("getRotateVideoUrl", {
- videoPath: endPointId + "/" + endPointId + "_rotate",
- sceneCode: settings.sceneCode,
- roomId: settings.roomId,
- userId: settings.userId,
- });
- // 要跳转的位置与当前位置相同的话,就直接跳过,否则动画会出bug
- if(nextPos.x == this.mesh.position.x && nextPos.z == this.mesh.position.z)
- {
- console.warn("跳转点位与当前点位相同, 已跳过!")
- let nextPointData = charactor.walkData.pathArr[++charactor.walkData.currentPoint]
- if(nextPointData && nextPointData.video) {
- charactor.walkByPath(charactorManager)
- } else {
- charactor.AniTransfromTo("Idle")
- charactorManager.app.cameraController.lockCamera(false)
- }
- return
- }
- let startingPoint = charactor.mesh.position.clone();
- startingPoint.y = nextPos.y;
- let walkDirc = nextPos.subtract(startingPoint).normalize();
- // 行走动画
- const walkAni = new BABYLON.Animation("walk", "position", settings.video.frameRate,
- BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE);
- let walkFrameNum = settings.video.frameRate * video.duration
- const walkKeyFrames = [{
- frame: 0,
- value: charactor.mesh.position
- },{
- frame: walkFrameNum,
- value: nextPos
- }];
- walkAni.setKeys(walkKeyFrames);
- // 转身动画
- const newQuar = BABYLON.Quaternion.FromUnitVectorsToRef(new BABYLON.Vector3(0, 0, 1), walkDirc, new BABYLON.Quaternion())
- const turnAroundAni = new BABYLON.Animation("turnAround", "rotationQuaternion", settings.video.frameRate,
- BABYLON.Animation.ANIMATIONTYPE_QUATERNION, BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE);
- let turnAroundFrameNum = settings.video.frameRate * 0.2 // 0.2秒的帧数
- const turnAroundFrames = [{
- frame: 0,
- value: charactor.mesh.rotationQuaternion
- },{
- frame: turnAroundFrameNum,
- value: newQuar
- }];
- turnAroundAni.setKeys(turnAroundFrames);
-
- charactorManager.app.scene.beginDirectAnimation(charactor.mesh, [walkAni, turnAroundAni], 0, Math.max(walkFrameNum, turnAroundFrameNum), false, 1,
- () => {
- // 如果还有下一个点位就继续走,否则变为站立
- let nextPointData = charactor.walkData.pathArr[++charactor.walkData.currentPoint]
- if(nextPointData && nextPointData.video) {
- charactor.walkByPath(charactorManager)
- } else {
- charactor.AniTransfromTo("Idle")
- charactorManager.app.cameraController.lockCamera(false)
- }
- });
- }
- }
|