100 lines
3.4 KiB
TypeScript
100 lines
3.4 KiB
TypeScript
/**
|
|
* @author MaHaiBing
|
|
* @email mlt131220@163.com
|
|
* @date 2024/8/3 22:49
|
|
* @description 包 骨骼处理
|
|
*/
|
|
import {Skeleton, Bone, Object3D } from "three";
|
|
|
|
export class PackageSkeleton{
|
|
// 场景内所有骨骼的map
|
|
private boneMap = new Map<string,Bone>();
|
|
// 场景内所有骨架的map <skeletonUuid:string,skeleton:Skeleton>
|
|
private skeletonsMap = new Map<string, Skeleton>();
|
|
// 骨架未对应上的骨骼 <boneUuid:string,skeleton:Skeleton[]>
|
|
private unMatchBoneMap = new Map<string, Skeleton[]>();
|
|
|
|
constructor() {
|
|
}
|
|
|
|
addBones(bones:Bone[]){
|
|
bones.forEach(bone => {
|
|
if(this.boneMap.has(bone.uuid)) return;
|
|
|
|
this.boneMap.set(bone.uuid,bone);
|
|
|
|
if(this.unMatchBoneMap.has(bone.uuid)){
|
|
const skeletons = this.unMatchBoneMap.get(bone.uuid) as Skeleton[];
|
|
|
|
skeletons.forEach(skeleton => {
|
|
skeleton.bones.push(bone);
|
|
|
|
// 骨骼找到一个替换一个loader.parse时对应骨骼(Bone)还未加载,生成的空骨骼
|
|
const d = skeleton.bones.findIndex(bone => bone.userData.waitDelete);
|
|
if(d === -1) return;
|
|
skeleton.bones.splice(d,1);
|
|
})
|
|
|
|
this.unMatchBoneMap.delete(bone.uuid);
|
|
}
|
|
})
|
|
}
|
|
|
|
handleSkeletons(skeletons,group:Object3D){
|
|
skeletons.forEach(skeleton => {
|
|
if(this.skeletonsMap.has(skeleton.uuid)) return;
|
|
|
|
let skinnedMesh;
|
|
group.traverse((m)=> {
|
|
if(!m.skeleton?.uuid) return;
|
|
|
|
if(m.skeleton.uuid === skeleton.uuid){
|
|
skinnedMesh = m;
|
|
}
|
|
})
|
|
if(!skinnedMesh) return;
|
|
|
|
// 此骨架的原骨骼(Bone)uuid数组
|
|
const bonesUuid:string[] = skeleton.bones;
|
|
|
|
// 对比skinnedMesh.skeleton.bones 和 skeleton.bones
|
|
for(let i = skinnedMesh.skeleton.bones.length;i > 0;i--){
|
|
const bone = skinnedMesh.skeleton.bones[i - 1];
|
|
const u = bonesUuid.indexOf(bone.uuid);
|
|
|
|
if(u === -1){
|
|
// 和原数组没匹配上,说明此骨骼不是原骨骼,是loader.parse时对应骨骼(Bone)还未加载,生成的新的空骨骼
|
|
// 但不能直接从skeleton中删除,需要之后找到对应骨骼一个一个替换
|
|
bone.userData.waitDelete = true;
|
|
}else{
|
|
bonesUuid.splice(u,1);
|
|
}
|
|
}
|
|
|
|
if(bonesUuid.length > 0){
|
|
// 在已存储的骨骼中寻找
|
|
for(let i = bonesUuid.length;i > 0;i--){
|
|
if(this.boneMap.has(bonesUuid[i])){
|
|
skinnedMesh.skeleton.bones.push(<Bone>this.boneMap.get(bonesUuid[i]));
|
|
|
|
bonesUuid.splice(i,1);
|
|
}
|
|
}
|
|
|
|
bonesUuid.forEach(uuid => {
|
|
const skeletons = this.unMatchBoneMap.get(uuid) || [];
|
|
skeletons.push(skinnedMesh.skeleton);
|
|
this.unMatchBoneMap.set(uuid,skeletons);
|
|
})
|
|
}
|
|
|
|
this.skeletonsMap.set(skeleton.uuid,skinnedMesh.skeleton);
|
|
})
|
|
}
|
|
|
|
clear(){
|
|
this.boneMap.clear();
|
|
this.skeletonsMap.clear();
|
|
this.unMatchBoneMap.clear();
|
|
}
|
|
} |