You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3105904 on 2016/08/30 by Ben.Marsh PR #2691: Copy .map-file to staging & cleanup (Contributed by projectgheist) Change 3105974 on 2016/08/30 by Ben.Marsh PR #2748: [Bug-Fix] UGS - Ensure older events do not trample newer ones (Contributed by paulevans) Change 3106035 on 2016/08/30 by Ben.Marsh PR #2746: [Bug-Fix] UGS - Starting build colour was the same as disabled (Contributed by paulevans) Change 3106172 on 2016/08/30 by Ben.Marsh UAT: Do not default to submitting build products from BuildCookRun unless -submit is explicitly specified on the command line. #codreview Maciej.Mroz Change 3107642 on 2016/08/31 by Matthew.Griffin More Monolithic editor fixes Fixed IMPLEMENT_MODULE macros with incorrect module name Wrapped some usages of GIsHotReload in WITH_HOT_RELOAD Fixed NiagaraConstants so that they can be used in multiple modules Change 3107808 on 2016/08/31 by Matthew.Griffin Added Node to Compile UAT on Mac to catch any Mono failures which will run as part of monolithics aggregate Change 3111527 on 2016/09/02 by Matthew.Griffin Duplicating CL#3111524 from Release-4.13 stream Including Documentation/Extras in installed build Change 3117683 on 2016/09/08 by Ben.Marsh PR #2771: Fix compilation of C# projects on case-sensitive OSes (Contributed by slonopotamus) Change 3119707 on 2016/09/09 by Ben.Marsh UBT: Add more explicit methods for querying Visual C++ and Visual Studio installation directories. Now uses the same logic in the Visual Studio batch files. Change 3120824 on 2016/09/12 by Ben.Marsh UnrealGameSync: Add a project-wide option which can disable using the last code changelist for version files, and use the sync changelist instead. ("VersionToLastCodeChange" in the "[Options]" section). Update version to 1.80. Change 3120996 on 2016/09/12 by Ben.Marsh Core: Fix lines of output text from FMonitoredProcess being truncated at 512 characters, due to pipe buffer size. Accumulate incomplete lines and merge them together again instead. Also remove CR-LF pairs if they occur at the end of a line. #jira UE-35659 Change 3121353 on 2016/09/12 by Ben.Marsh Core: Manually enumerate and load dependent DLLs for modules by the editor, to work around limitations in the number of search paths checked by the Windows loader. We previously temporarily modified the PATH environment variable to provide this functionality, but are close to the OS limit for length of that string. This method should not have any such restrictions (though it will not work for circular dependencies). Change 3121996 on 2016/09/12 by Ben.Marsh Add support for Visual Studio 2017 (aka "15"; assuming consistent naming with other versions until final name is announced). * Compiler, STL implementation and CRT are binary compatible with VS2015 (see https://blogs.msdn.microsoft.com/vcblog/2016/08/24/c1417-features-and-stl-fixes-in-vs-15-preview-4/), so no new third-party libraries needed so far. WindowsPlatform.GetVisualStudioCompilerVersionName() returns "2015" as a result. * Default compiler for compiling and generating project files is still VS 2015 for now. Pass -2017 on the command line to GenerateProjectFiles.bat to generate VS2017 projects. Projects generated for VS2017 will use the 2017 compiler by default. * Visual Studio source code accessor can talk to VS 2017 instances. * Added a VS2017 configuration for UnrealVS, and added precompiled vsix package. * Switched GetVSComnTools to check the SOFTWARE\Microsoft\VisualStudio\SxS\VS7 registry key rather than the individual product install registry key. "15" doesn't seem to have it's own "InstallDir" key, but this system seems to work for all versions of Visual Studio (including previous releases of VS Express). * Removed ATL dependency from VisualStudioSourceCodeAccessor. It's not installed with VS by default any more, and is only used for a couple of smart pointer classes. Tested running the editor and packaging TP_Flying for Win64. Packaging from the editor still defaults to using the 2015 compiler, so ConfigureToolchain() needs to be overriden from the .target.cs file if multiple Visual Studio versions are installed. Change 3123144 on 2016/09/13 by Ben.Marsh BuildGraph: Fix exception due to mismatched argument lists. Change 3123160 on 2016/09/13 by Ben.Marsh Linux: Make PLATFORM_SUPPORTS_JEMALLOC a globally defined macro rather than just defined by the jemalloc module. Core supplies a default value for this macro which is inconsistent unless your module has an explicit dependency on jemalloc. Change 3123211 on 2016/09/13 by Ben.Marsh UBT: Fix exception writing a version manifest if the output directory does not exist. Change 3125300 on 2016/09/14 by Ben.Marsh UnrealVS: Few fixes to single-file compile command. * All documents are now saved before compile starts. * Now gives a useful error when trying to compile non-cpp files, rather than falling back to the invalid default command handler. * Trying to do a single-file compile while an existing build is running now prompts to stop it, rather than falling back to the default command handler (which gives a "Invalid command" message for makefile projects) Change 3125437 on 2016/09/14 by Ben.Marsh UnrealVS: Update version number to 1.43 in order to prevent installer from bailing unless existing version is uninstalled first. [CL 3126342 by Ben Marsh in Main branch]
311 lines
10 KiB
C++
311 lines
10 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Engine.h"
|
|
#include "MeshBoneReduction.h"
|
|
#include "Developer/MeshUtilities/Public/MeshUtilities.h"
|
|
#include "ComponentReregisterContext.h"
|
|
|
|
class FMeshBoneReductionModule : public IMeshBoneReductionModule
|
|
{
|
|
public:
|
|
// IModuleInterface interface.
|
|
virtual void StartupModule() override;
|
|
virtual void ShutdownModule() override;
|
|
|
|
// IMeshBoneReductionModule interface.
|
|
virtual class IMeshBoneReduction* GetMeshBoneReductionInterface() override;
|
|
};
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogMeshBoneReduction, Log, All);
|
|
IMPLEMENT_MODULE(FMeshBoneReductionModule, MeshBoneReduction);
|
|
|
|
class FMeshBoneReduction : public IMeshBoneReduction
|
|
{
|
|
public:
|
|
|
|
virtual ~FMeshBoneReduction()
|
|
{
|
|
}
|
|
|
|
void EnsureChildrenPresents(FBoneIndexType BoneIndex, const TArray<FMeshBoneInfo>& RefBoneInfo, TArray<FBoneIndexType>& OutBoneIndicesToRemove)
|
|
{
|
|
// just look for direct parent, we could look for RefBoneInfo->Ischild, but more expensive, and no reason to do that all the work
|
|
for (int32 ChildBoneIndex = 0; ChildBoneIndex < RefBoneInfo.Num(); ++ChildBoneIndex)
|
|
{
|
|
if (RefBoneInfo[ChildBoneIndex].ParentIndex == BoneIndex)
|
|
{
|
|
OutBoneIndicesToRemove.AddUnique(ChildBoneIndex);
|
|
EnsureChildrenPresents(ChildBoneIndex, RefBoneInfo, OutBoneIndicesToRemove);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GetBoneReductionData(const USkeletalMesh* SkeletalMesh, int32 DesiredLOD, TMap<FBoneIndexType, FBoneIndexType>& OutBonesToReplace, const TArray<FName>* BoneNamesToRemove = NULL) override
|
|
{
|
|
if (!SkeletalMesh)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!SkeletalMesh->LODInfo.IsValidIndex(DesiredLOD))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const TArray<FMeshBoneInfo> & RefBoneInfo = SkeletalMesh->RefSkeleton.GetRefBoneInfo();
|
|
TArray<FBoneIndexType> BoneIndicesToRemove;
|
|
|
|
// originally this code was accumulating from LOD 0->DesiredLOd, but that should be done outside of tool if they want to
|
|
// removing it, and just include DesiredLOD
|
|
{
|
|
// if name is entered, use them instead of setting
|
|
const TArray<FName>& BonesToRemoveSetting = (BoneNamesToRemove) ? *BoneNamesToRemove : SkeletalMesh->LODInfo[DesiredLOD].RemovedBones;
|
|
|
|
// first gather indices. we don't want to add bones to replace if that "to-be-replace" will be removed as well
|
|
for (int32 Index = 0; Index < BonesToRemoveSetting.Num(); ++Index)
|
|
{
|
|
int32 BoneIndex = SkeletalMesh->RefSkeleton.FindBoneIndex(BonesToRemoveSetting[Index]);
|
|
|
|
// we don't allow root to be removed
|
|
if ( BoneIndex > 0 )
|
|
{
|
|
BoneIndicesToRemove.AddUnique(BoneIndex);
|
|
// make sure all children for this joint is included
|
|
EnsureChildrenPresents(BoneIndex, RefBoneInfo, BoneIndicesToRemove);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (BoneIndicesToRemove.Num() <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// now make sure the parent isn't the one to be removed, find the one that won't be removed
|
|
for (int32 Index = 0; Index < BoneIndicesToRemove.Num(); ++Index)
|
|
{
|
|
int32 BoneIndex = BoneIndicesToRemove[Index];
|
|
int32 ParentIndex = RefBoneInfo[BoneIndex].ParentIndex;
|
|
|
|
while (BoneIndicesToRemove.Contains(ParentIndex))
|
|
{
|
|
ParentIndex = RefBoneInfo[ParentIndex].ParentIndex;
|
|
}
|
|
|
|
OutBonesToReplace.Add(BoneIndex, ParentIndex);
|
|
}
|
|
|
|
return ( OutBonesToReplace.Num() > 0 );
|
|
}
|
|
|
|
void FixUpSectionBoneMaps( FSkelMeshSection & Section, const TMap<FBoneIndexType, FBoneIndexType> &BonesToRepair ) override
|
|
{
|
|
// now you have list of bones, remove them from vertex influences
|
|
{
|
|
TMap<uint8, uint8> BoneMapRemapTable;
|
|
// first go through bone map and see if this contains BonesToRemove
|
|
int32 BoneMapSize = Section.BoneMap.Num();
|
|
int32 AdjustIndex=0;
|
|
|
|
for (int32 BoneMapIndex=0; BoneMapIndex < BoneMapSize; ++BoneMapIndex )
|
|
{
|
|
// look for this bone to be removed or not?
|
|
const FBoneIndexType* ParentBoneIndex = BonesToRepair.Find(Section.BoneMap[BoneMapIndex]);
|
|
if ( ParentBoneIndex )
|
|
{
|
|
// this should not happen, I don't ever remove root
|
|
check (*ParentBoneIndex!=INDEX_NONE);
|
|
|
|
// if Parent already exists in the current BoneMap, we just have to fix up the mapping
|
|
int32 ParentBoneMapIndex = Section.BoneMap.Find(*ParentBoneIndex);
|
|
|
|
// if it exists
|
|
if (ParentBoneMapIndex != INDEX_NONE)
|
|
{
|
|
// if parent index is higher, we have to decrease it to match to new index
|
|
if (ParentBoneMapIndex > BoneMapIndex)
|
|
{
|
|
--ParentBoneMapIndex;
|
|
}
|
|
|
|
// remove current section count, will replace with parent
|
|
Section.BoneMap.RemoveAt(BoneMapIndex);
|
|
}
|
|
else
|
|
{
|
|
// if parent doens't exists, we have to add one
|
|
// this doesn't change bone map size
|
|
Section.BoneMap.RemoveAt(BoneMapIndex);
|
|
ParentBoneMapIndex = Section.BoneMap.Add(*ParentBoneIndex);
|
|
}
|
|
|
|
// first fix up all indices of BoneMapRemapTable for the indices higher than BoneMapIndex, since BoneMapIndex is being removed
|
|
for (auto Iter = BoneMapRemapTable.CreateIterator(); Iter; ++Iter)
|
|
{
|
|
uint8& Value = Iter.Value();
|
|
|
|
check (Value != BoneMapIndex);
|
|
if (Value > BoneMapIndex)
|
|
{
|
|
--Value;
|
|
}
|
|
}
|
|
|
|
int32 OldIndex = BoneMapIndex+AdjustIndex;
|
|
int32 NewIndex = ParentBoneMapIndex;
|
|
// you still have to add no matter what even if same since indices might change after added
|
|
{
|
|
// add to remap table
|
|
check (OldIndex < 256 && OldIndex >= 0);
|
|
check (NewIndex < 256 && NewIndex >= 0);
|
|
check (BoneMapRemapTable.Contains((uint8)OldIndex) == false);
|
|
BoneMapRemapTable.Add((uint8)OldIndex, (uint8)NewIndex);
|
|
}
|
|
|
|
// reduce index since the item is removed
|
|
--BoneMapIndex;
|
|
--BoneMapSize;
|
|
|
|
// this is to adjust the later indices. We need to refix their indices
|
|
++AdjustIndex;
|
|
}
|
|
else if (AdjustIndex > 0)
|
|
{
|
|
int32 OldIndex = BoneMapIndex+AdjustIndex;
|
|
int32 NewIndex = BoneMapIndex;
|
|
|
|
check (OldIndex < 256 && OldIndex >= 0);
|
|
check (NewIndex < 256 && NewIndex >= 0);
|
|
check (BoneMapRemapTable.Contains((uint8)OldIndex) == false);
|
|
BoneMapRemapTable.Add((uint8)OldIndex, (uint8)NewIndex);
|
|
}
|
|
}
|
|
|
|
if ( BoneMapRemapTable.Num() > 0 )
|
|
{
|
|
// fix up soft verts
|
|
for (int32 VertIndex=0; VertIndex < Section.SoftVertices.Num(); ++VertIndex)
|
|
{
|
|
FSoftSkinVertex & Vert = Section.SoftVertices[VertIndex];
|
|
bool ShouldRenormalize = false;
|
|
|
|
for(int32 InfluenceIndex = 0;InfluenceIndex < MAX_TOTAL_INFLUENCES;InfluenceIndex++)
|
|
{
|
|
uint8 *RemappedBone = BoneMapRemapTable.Find(Vert.InfluenceBones[InfluenceIndex]);
|
|
if (RemappedBone)
|
|
{
|
|
Vert.InfluenceBones[InfluenceIndex] = *RemappedBone;
|
|
ShouldRenormalize = true;
|
|
}
|
|
}
|
|
|
|
if (ShouldRenormalize)
|
|
{
|
|
// should see if same bone exists
|
|
for(int32 InfluenceIndex = 0;InfluenceIndex < MAX_TOTAL_INFLUENCES;InfluenceIndex++)
|
|
{
|
|
for(int32 InfluenceIndex2 = InfluenceIndex+1;InfluenceIndex2 < MAX_TOTAL_INFLUENCES;InfluenceIndex2++)
|
|
{
|
|
// cannot be 0 because we don't allow removing root
|
|
if (Vert.InfluenceBones[InfluenceIndex] != 0 && Vert.InfluenceBones[InfluenceIndex] == Vert.InfluenceBones[InfluenceIndex2])
|
|
{
|
|
Vert.InfluenceWeights[InfluenceIndex] += Vert.InfluenceWeights[InfluenceIndex2];
|
|
// reset
|
|
Vert.InfluenceBones[InfluenceIndex2] = 0;
|
|
Vert.InfluenceWeights[InfluenceIndex2] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ReduceBoneCounts(USkeletalMesh* SkeletalMesh, int32 DesiredLOD, const TArray<FName>* BoneNamesToRemove) override
|
|
{
|
|
check (SkeletalMesh);
|
|
USkeleton* Skeleton = SkeletalMesh->Skeleton;
|
|
check (Skeleton);
|
|
|
|
// find all the bones to remove from Skeleton settings
|
|
TMap<FBoneIndexType, FBoneIndexType> BonesToRemove;
|
|
|
|
if (GetBoneReductionData(SkeletalMesh, DesiredLOD, BonesToRemove, BoneNamesToRemove) == false)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TComponentReregisterContext<USkinnedMeshComponent> ReregisterContext;
|
|
SkeletalMesh->ReleaseResources();
|
|
SkeletalMesh->ReleaseResourcesFence.Wait();
|
|
|
|
FSkeletalMeshResource* SkeletalMeshResource = SkeletalMesh->GetImportedResource();
|
|
check(SkeletalMeshResource);
|
|
|
|
FStaticLODModel** LODModels = SkeletalMeshResource->LODModels.GetData();
|
|
FStaticLODModel* SrcModel = LODModels[DesiredLOD];
|
|
FStaticLODModel* NewModel = new FStaticLODModel();
|
|
LODModels[DesiredLOD] = NewModel;
|
|
|
|
// Bulk data arrays need to be locked before a copy can be made.
|
|
SrcModel->RawPointIndices.Lock( LOCK_READ_ONLY );
|
|
SrcModel->LegacyRawPointIndices.Lock( LOCK_READ_ONLY );
|
|
*NewModel = *SrcModel;
|
|
SrcModel->RawPointIndices.Unlock();
|
|
SrcModel->LegacyRawPointIndices.Unlock();
|
|
|
|
// The index buffer needs to be rebuilt on copy.
|
|
FMultiSizeIndexContainerData IndexBufferData, AdjacencyIndexBufferData;
|
|
SrcModel->MultiSizeIndexContainer.GetIndexBufferData( IndexBufferData );
|
|
SrcModel->AdjacencyMultiSizeIndexContainer.GetIndexBufferData( AdjacencyIndexBufferData );
|
|
NewModel->RebuildIndexBuffer( &IndexBufferData, &AdjacencyIndexBufferData );
|
|
|
|
// fix up chunks
|
|
for ( int32 SectionIndex=0; SectionIndex< NewModel->Sections.Num(); ++SectionIndex)
|
|
{
|
|
FixUpSectionBoneMaps(NewModel->Sections[SectionIndex], BonesToRemove);
|
|
}
|
|
|
|
// fix up RequiredBones/ActiveBoneIndices
|
|
for(auto Iter = BonesToRemove.CreateIterator(); Iter; ++Iter)
|
|
{
|
|
FBoneIndexType BoneIndex = Iter.Key();
|
|
FBoneIndexType MappingIndex = Iter.Value();
|
|
NewModel->ActiveBoneIndices.Remove(BoneIndex);
|
|
NewModel->RequiredBones.Remove(BoneIndex);
|
|
|
|
NewModel->ActiveBoneIndices.AddUnique(MappingIndex);
|
|
NewModel->RequiredBones.AddUnique(MappingIndex);
|
|
}
|
|
|
|
NewModel->ActiveBoneIndices.Sort();
|
|
NewModel->RequiredBones.Sort();
|
|
|
|
SkeletalMesh->PostEditChange();
|
|
SkeletalMesh->InitResources();
|
|
SkeletalMesh->MarkPackageDirty();
|
|
|
|
delete SrcModel;
|
|
|
|
return true;
|
|
}
|
|
};
|
|
|
|
TScopedPointer<FMeshBoneReduction> GMeshBoneReduction;
|
|
|
|
void FMeshBoneReductionModule::StartupModule()
|
|
{
|
|
GMeshBoneReduction = new FMeshBoneReduction();
|
|
}
|
|
|
|
void FMeshBoneReductionModule::ShutdownModule()
|
|
{
|
|
GMeshBoneReduction = NULL;
|
|
}
|
|
|
|
IMeshBoneReduction* FMeshBoneReductionModule::GetMeshBoneReductionInterface()
|
|
{
|
|
return GMeshBoneReduction;
|
|
}
|