Add Games File

This commit is contained in:
Ivan Anikin
2026-05-19 13:42:41 +07:00
parent 7908479e0c
commit 12e7e22c1a
3672 changed files with 125922 additions and 0 deletions
@@ -0,0 +1,383 @@
// VRM4U Copyright (c) 2021-2024 Haruyoshi Yamamoto. This software is released under the MIT License.
#include "VrmConvertHumanoid.h"
#include "VrmConvert.h"
#include "VrmUtil.h"
#include "VrmAssetListObject.h"
#include "VrmMetaObject.h"
#include "Engine/SkeletalMesh.h"
#include "RenderingThread.h"
#include "Rendering/SkeletalMeshModel.h"
#include "Rendering/SkeletalMeshLODModel.h"
#include "Rendering/SkeletalMeshLODRenderData.h"
#include "Rendering/SkeletalMeshRenderData.h"
#include "Animation/MorphTarget.h"
#include "Animation/Skeleton.h"
#include "Animation/NodeMappingContainer.h"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/mesh.h>
#include <assimp/postprocess.h>
#include <assimp/GltfMaterial.h>
#include <assimp/vrm/vrmmeta.h>
static void renameToHumanoidBone(USkeletalMesh *targetSK, const UVrmMetaObject *meta, const USkeletalMesh *srcSK) {
USkeleton *targetSkeleton = VRMGetSkeleton(targetSK);
UNodeMappingContainer* rig = nullptr;
if (VRMGetNodeMappingData(targetSK).Num()) {
rig = VRMGetNodeMappingData(targetSK)[0];
}
UNodeMappingContainer* src_rig = nullptr;
if (VRMGetNodeMappingData(srcSK).Num()) {
src_rig = VRMGetNodeMappingData(srcSK)[0];
}
if (meta == nullptr) {
return;
}
//k->RemoveBonesFromSkeleton()
auto &allbone = const_cast<TArray<FMeshBoneInfo> &>(targetSkeleton->GetReferenceSkeleton().GetRawRefBoneInfo());
TMap<FName, FName> changeTable;
{
bool bHasRoot = false;
for (auto& a : allbone) {
if (a.Name == TEXT("Root")) {
a.Name = TEXT("root");
#if WITH_EDITORONLY_DATA
a.ExportName = TEXT("root");
#endif
bHasRoot = true;
break;
}
}
if (bHasRoot == false) {
if (allbone[0].Name != TEXT("hip")) {
allbone[0].Name = TEXT("root");
#if WITH_EDITORONLY_DATA
allbone[0].ExportName = TEXT("root");
#endif
}
}
}
for (auto &a : allbone) {
auto p = meta->humanoidBoneTable.FindKey(a.Name.ToString());
if (p == nullptr) {
continue;
}
if (p->IsEmpty()) {
continue;
}
for (auto &b : allbone) {
if (a == b) continue;
if (b.Name == **p) {
b.Name = *(b.Name.ToString() + TEXT("_renamed_vrm4u"));
}
}
changeTable.Add(a.Name, **p);
a.Name = **p;
#if WITH_EDITORONLY_DATA
a.ExportName = **p;
#endif
}
const_cast<FReferenceSkeleton&>(targetSkeleton->GetReferenceSkeleton()).RebuildRefSkeleton(targetSkeleton, true);
VRMSetRefSkeleton(targetSK, targetSkeleton->GetReferenceSkeleton());
#if WITH_EDITOR
#if UE_VERSION_OLDER_THAN(4,20,0)
#elif UE_VERSION_OLDER_THAN(5,4,0)
if (src_rig) {
rig->SetSourceAsset(src_rig->GetSourceAsset());
rig->SetTargetAsset(targetSK);
targetSkeleton->RefreshRigConfig();
{
auto &table = src_rig->GetNodeMappingTable();
for (auto &t : table) {
FName n = t.Value;
{
auto *ret = changeTable.Find(t.Value);
if (ret) {
n = *ret;
}
}
rig->AddMapping(t.Key, n);
targetSkeleton->SetRigBoneMapping(t.Key, n);
}
}
rig->PostEditChange();
}
#else
// ue5.4 no rig data
#endif
#endif
}
static void renameToUE4Bone(USkeletalMesh *targetSK, UVrmMetaObject *meta, const USkeletalMesh *srcSK) {
USkeleton *targetSkeleton = VRMGetSkeleton(targetSK);
UNodeMappingContainer* rig = nullptr;
if (VRMGetNodeMappingData(targetSK).Num()) {
rig = VRMGetNodeMappingData(targetSK)[0];
}
UNodeMappingContainer* src_rig = nullptr;
if (VRMGetNodeMappingData(srcSK).Num()) {
src_rig = VRMGetNodeMappingData(srcSK)[0];
}
//k->RemoveBonesFromSkeleton()
auto &allbone = const_cast<TArray<FMeshBoneInfo> &>(targetSkeleton->GetReferenceSkeleton().GetRawRefBoneInfo());
TMap<FName, FName> changeTable;
allbone[0].Name = TEXT("root");
#if WITH_EDITORONLY_DATA
allbone[0].ExportName = TEXT("root");
#endif
for (auto &a : allbone) {
FString toVRMBone;
for (auto& tmp : meta->humanoidBoneTable) {
if (a.Name.ToString().ToLower() != tmp.Value.ToLower()) continue;
toVRMBone = tmp.Key;
break;
}
if (toVRMBone == "") continue;
FString toUE4Bone;
for (auto& tmp : VRMUtil::table_ue4_vrm) {
if (toVRMBone.ToLower() != tmp.BoneVRM.ToLower()) continue;
toUE4Bone = tmp.BoneUE4;
break;
}
if (toUE4Bone == "") continue;
FString newName = toUE4Bone;
for (auto &b : allbone) {
if (a == b) continue;
if (b.Name == *(newName.ToLower())) {
b.Name = *(b.Name.ToString() + TEXT("_renamed_vrm4u"));
}
}
changeTable.Add(a.Name, *newName);
a.Name = *newName;
#if WITH_EDITORONLY_DATA
a.ExportName = *newName;
#endif
}
const_cast<FReferenceSkeleton&>(targetSkeleton->GetReferenceSkeleton()).RebuildRefSkeleton(targetSkeleton, true);
VRMSetRefSkeleton(targetSK, targetSkeleton->GetReferenceSkeleton());
#if WITH_EDITOR
#if UE_VERSION_OLDER_THAN(4,20,0)
#elif UE_VERSION_OLDER_THAN(5,4,0)
if (src_rig) {
rig->SetSourceAsset(src_rig->GetSourceAsset());
rig->SetTargetAsset(targetSK);
targetSkeleton->RefreshRigConfig();
{
auto &table = src_rig->GetNodeMappingTable();
for (auto &t : table) {
FName n = t.Value;
{
auto *ret = changeTable.Find(t.Value);
if (ret) {
n = *ret;
}
}
rig->AddMapping(t.Key, n);
targetSkeleton->SetRigBoneMapping(t.Key, n);
}
}
rig->PostEditChange();
}
#else
// ue5.4 no rig data
#endif
#endif
}
bool VRMConverter::ConvertHumanoid(UVrmAssetListObject *vrmAssetList) {
if (Options::Get().IsGenerateHumanoidRenamedMesh() == false) {
return true;
}
const USkeletalMesh *src_sk = vrmAssetList->SkeletalMesh;
const USkeleton *src_k = VRMGetSkeleton(src_sk);
const UNodeMappingContainer *src_rig = nullptr;
if (VRMGetNodeMappingData(src_sk).Num()) {
src_rig = VRMGetNodeMappingData(src_sk)[0];
}
USkeletalMesh *new_sk[2] = {};
USkeleton *new_k[2] = {};
UNodeMappingContainer *new_rig[2] = {};
// 0: humanoid
// 1: ue4mannequin
for (int i = 0; i < 2; ++i) {
FString name_skeleton;
FString name_mesh;
FString name_rig;
if (i == 0) {
name_skeleton = (TEXT("SKEL_") + vrmAssetList->BaseFileName + TEXT("_humanoid"));
name_mesh = (FString(TEXT("SK_")) + vrmAssetList->BaseFileName + TEXT("_humanoid"));
name_rig = (FString(TEXT("RIG_")) + vrmAssetList->BaseFileName + TEXT("_humanoid"));
} else {
name_skeleton = (TEXT("SKEL_") + vrmAssetList->BaseFileName + TEXT("_ue4mannequin"));
name_mesh = (FString(TEXT("SK_")) + vrmAssetList->BaseFileName + TEXT("_ue4mannequin"));
name_rig = (FString(TEXT("RIG_")) + vrmAssetList->BaseFileName + TEXT("_ue4mannequin"));
}
USkeleton *base = nullptr;
USkeletalMesh *ss = nullptr;
UNodeMappingContainer *rr = nullptr;
#if WITH_EDITOR
{
auto p = vrmAssetList->Package;
if (i == 0) {
ss = VRM4U_DuplicateObject<USkeletalMesh>(src_sk, p, *name_mesh);
base = VRM4U_DuplicateObject<USkeleton>(src_k, p, *name_skeleton);
if (src_rig) {
rr = VRM4U_NewObject<UNodeMappingContainer>(p, *name_rig, RF_Public | RF_Standalone);
}
}else {
ss = VRM4U_DuplicateObject<USkeletalMesh>(src_sk, p, *name_mesh);
base = VRM4U_DuplicateObject<USkeleton>(src_k, p, *name_skeleton);
if (src_rig) {
rr = VRM4U_NewObject<UNodeMappingContainer>(p, *name_rig, RF_Public | RF_Standalone);
}
}
}
#else
ss = const_cast<USkeletalMesh*>(src_sk);
base = const_cast<USkeleton*>(src_k);
if (i == 1) continue;
#endif
new_sk[i] = ss;
new_k[i] = base;
new_rig[i] = rr;
VRMSetSkeleton(ss, base);
VRMGetNodeMappingData(ss).Empty();
VRMGetNodeMappingData(ss).Add(rr);
if (i == 0) {
// org -> humanoid
renameToHumanoidBone(ss, vrmAssetList->VrmMetaObject, src_sk);
} else {
// humanoid -> ue4mannequin
renameToUE4Bone(ss, vrmAssetList->VrmMetaObject, src_sk);
}
ss->CalculateInvRefMatrices();
ss->CalculateExtendedBounds();
#if WITH_EDITORONLY_DATA
ss->ConvertLegacyLODScreenSize();
#if UE_VERSION_OLDER_THAN(4,20,0)
#else
ss->UpdateGenerateUpToData();
#endif
#endif
#if WITH_EDITORONLY_DATA
base->SetPreviewMesh(ss);
#endif
base->RecreateBoneTree(ss);
// retarget mode
for (int bon = 0; bon < base->GetReferenceSkeleton().GetRawBoneNum(); ++bon) {
auto type = src_k->GetBoneTranslationRetargetingMode(bon);
base->SetBoneTranslationRetargetingMode(bon, type);
}
if (i == 0) {
vrmAssetList->HumanoidSkeletalMesh = ss;
vrmAssetList->VrmHumanoidMetaObject->SkeletalMesh = ss;
} else {
vrmAssetList->UE4SkeletalMesh = ss;
vrmAssetList->VrmMannequinMetaObject->SkeletalMesh = ss;
}
}
// meta rename check
// 0: humanoid
// 1: ue4mannequin
for (int i = 0; i < 2; ++i) {
USkeleton* base = nullptr;
USkeletalMesh* ss = nullptr;
UNodeMappingContainer* rr = nullptr;
UVrmMetaObject* meta = nullptr;
if (i == 0) {
ss = vrmAssetList->HumanoidSkeletalMesh;
base = VRMGetSkeleton(ss);
meta = vrmAssetList->VrmHumanoidMetaObject;
} else {
ss = vrmAssetList->UE4SkeletalMesh;
base = VRMGetSkeleton(ss);
meta = vrmAssetList->VrmMannequinMetaObject;
}
int boneNo = 0;
TPair<FString, FString> prev;
for (auto& a : meta->humanoidBoneTable) {
if (ss==nullptr) break;
auto ind = VRMGetRefSkeleton(ss).FindBoneIndex(*(a.Value));
if (boneNo == 0) {
prev = a;
}
if (ind == INDEX_NONE && a.Value!="") {
// set prev bone name
a.Value = prev.Value;
}
prev = a;
++boneNo;
}
}
return true;
}
VrmConvertHumanoid::VrmConvertHumanoid()
{
}
VrmConvertHumanoid::~VrmConvertHumanoid()
{
}