2019-12-26 15:32:37 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2017-09-15 11:19:07 -04:00
|
|
|
|
|
|
|
|
#include "MeshDescriptionHelper.h"
|
|
|
|
|
|
2020-01-23 16:28:59 -05:00
|
|
|
#include "BuildStatisticManager.h"
|
2017-09-15 11:19:07 -04:00
|
|
|
#include "CoreMinimal.h"
|
|
|
|
|
#include "CoreTypes.h"
|
|
|
|
|
#include "Engine/EngineTypes.h"
|
2017-09-25 13:46:28 -04:00
|
|
|
#include "Engine/StaticMesh.h"
|
2017-11-01 18:22:05 -04:00
|
|
|
#include "IMeshReductionInterfaces.h"
|
|
|
|
|
#include "IMeshReductionManagerModule.h"
|
2017-12-28 17:15:00 -05:00
|
|
|
#include "Materials/Material.h"
|
2018-03-07 09:10:20 -05:00
|
|
|
#include "Modules/ModuleManager.h"
|
2020-01-23 16:28:59 -05:00
|
|
|
#include "RawMesh.h"
|
|
|
|
|
#include "RenderUtils.h"
|
|
|
|
|
#include "StaticMeshAttributes.h"
|
|
|
|
|
#include "Serialization/MemoryWriter.h"
|
|
|
|
|
#include "Serialization/MemoryReader.h"
|
|
|
|
|
#include "StaticMeshOperations.h"
|
|
|
|
|
#include "UObject/Package.h"
|
|
|
|
|
#include "UObject/UObjectGlobals.h"
|
2017-09-22 17:58:06 -04:00
|
|
|
|
|
|
|
|
//Enable all check
|
|
|
|
|
//#define ENABLE_NTB_CHECK
|
|
|
|
|
|
2018-01-11 17:52:50 -05:00
|
|
|
DEFINE_LOG_CATEGORY(LogMeshDescriptionBuildStatistic);
|
|
|
|
|
|
2018-06-07 16:22:56 -04:00
|
|
|
FMeshDescriptionHelper::FMeshDescriptionHelper(FMeshBuildSettings* InBuildSettings)
|
|
|
|
|
: BuildSettings(InBuildSettings)
|
2017-09-15 11:19:07 -04:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-27 02:14:48 -04:00
|
|
|
void FMeshDescriptionHelper::SetupRenderMeshDescription(UObject* Owner, FMeshDescription& RenderMeshDescription, bool bForNanite, bool bNeedTangents)
|
2017-09-15 11:19:07 -04:00
|
|
|
{
|
2021-04-29 19:32:06 -04:00
|
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FMeshDescriptionHelper::SetupRenderMeshDescription);
|
2019-10-04 13:11:45 -04:00
|
|
|
|
2017-09-25 13:46:28 -04:00
|
|
|
UStaticMesh* StaticMesh = Cast<UStaticMesh>(Owner);
|
|
|
|
|
check(StaticMesh);
|
2017-09-15 11:19:07 -04:00
|
|
|
|
2022-09-27 02:14:48 -04:00
|
|
|
float ComparisonThreshold = (BuildSettings->bRemoveDegenerates && !bForNanite) ? THRESH_POINTS_ARE_SAME : 0.0f;
|
2018-04-16 17:40:43 -04:00
|
|
|
|
2021-10-12 21:21:22 -04:00
|
|
|
// Compact the mesh description prior to performing operations
|
Significant DDC memory and perfomance optimizations to Nanite landscape mesh builds (and some general optimizations to all Nanite mesh builds). In some content cooks with extremely dense Nanite landscape mesh where the process memory well exceeded ~22gb, this brings it down to ~13gb, along with faster processing times.
Highlights:
* Only allocate and use a wedge map for non-Nanite LODs, or if the mesh is sub 300kindices and it will be cache optimized
* Only allocate and use a remap if there are no overlapping corners
* When the Nanite landscape mesh is created, we now ensure the mesh description is fully compacted, computed, and optimized prior to committing it, along with making sure there are no overlapping corners.
* Since Nanite landscape is checked to ensure no overlapping corners before the build, we can also now skip computing the overlapping corners, which was an intense number of tiny allocations.
* When Nanite landscape is being built as a static mesh, we now avoid super expensive temporary copies of the mesh description, knowing that no actual mutation will occur.
* The original code (after building) would release the memory from the mesh description copy, but it would not release the original immutable cached copy from memory (now that is released too)
* Fixed NaniteLODIndex incorrectly creating a mesh description at a LOD other than the expected 0
* Removed a full loop over all vertex positions by calculating the bounding box while we're building the vertex buffer (and already processing every vertex)
* Added a NeedsCompact() helper to MeshDescription to avoid expensive and unnecessary Compact() calls that do lots of reallocs/copies even if the mesh description is already contiguous\packed in memory.
* Skip building distance field and mesh card representations for the Nanite landscape mesh, which also avoids more cached mesh description deserialization and copies into memory.
Note: In the near future the APIs around this wil be cleaned up further.
#rb richard.talbotwatkin, yuriy.odonnell
[FYI] zousar.shaker, brian.karis, rune.stubbe, juan.canada, danny.couture
#preflight 640b7390482188d710464d39
[CL 24601442 by graham wihlidal in ue5-main branch]
2023-03-10 20:03:17 -05:00
|
|
|
if (RenderMeshDescription.NeedsCompact())
|
2021-10-12 21:21:22 -04:00
|
|
|
{
|
|
|
|
|
FElementIDRemappings Remappings;
|
|
|
|
|
RenderMeshDescription.Compact(Remappings);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-01 09:26:52 -04:00
|
|
|
//Make sure we do not have nan or infinite float in the mesh description data
|
|
|
|
|
FStaticMeshOperations::ValidateAndFixData(RenderMeshDescription, Owner->GetName());
|
|
|
|
|
|
2020-01-23 16:28:59 -05:00
|
|
|
//This function make sure the Polygon Normals Tangents Binormals are computed and also remove degenerated triangle from the render mesh description.
|
2023-02-11 12:51:08 -05:00
|
|
|
FStaticMeshOperations::ComputeTriangleTangentsAndNormals(RenderMeshDescription, ComparisonThreshold, *Owner->GetPathName());
|
2017-09-22 17:58:06 -04:00
|
|
|
|
2019-10-23 06:44:22 -04:00
|
|
|
FVertexInstanceArray& VertexInstanceArray = RenderMeshDescription.VertexInstances();
|
2020-07-16 08:23:15 -04:00
|
|
|
|
|
|
|
|
FStaticMeshAttributes Attributes(RenderMeshDescription);
|
2021-05-05 15:07:25 -04:00
|
|
|
TVertexInstanceAttributesRef<FVector3f> Normals = Attributes.GetVertexInstanceNormals();
|
|
|
|
|
TVertexInstanceAttributesRef<FVector3f> Tangents = Attributes.GetVertexInstanceTangents();
|
2020-07-16 08:23:15 -04:00
|
|
|
TVertexInstanceAttributesRef<float> BinormalSigns = Attributes.GetVertexInstanceBinormalSigns();
|
2017-11-02 16:53:04 -04:00
|
|
|
|
2017-11-03 15:58:34 -04:00
|
|
|
// Find overlapping corners to accelerate adjacency.
|
2020-01-23 16:28:59 -05:00
|
|
|
FStaticMeshOperations::FindOverlappingCorners(OverlappingCorners, RenderMeshDescription, ComparisonThreshold);
|
2017-11-03 15:58:34 -04:00
|
|
|
|
2020-10-26 13:09:34 -04:00
|
|
|
// Static meshes always blend normals of overlapping corners.
|
|
|
|
|
EComputeNTBsFlags ComputeNTBsOptions = EComputeNTBsFlags::BlendOverlappingNormals;
|
|
|
|
|
ComputeNTBsOptions |= BuildSettings->bComputeWeightedNormals ? EComputeNTBsFlags::WeightedNTBs : EComputeNTBsFlags::None;
|
|
|
|
|
ComputeNTBsOptions |= BuildSettings->bRecomputeNormals ? EComputeNTBsFlags::Normals : EComputeNTBsFlags::None;
|
|
|
|
|
ComputeNTBsOptions |= BuildSettings->bUseMikkTSpace ? EComputeNTBsFlags::UseMikkTSpace : EComputeNTBsFlags::None;
|
|
|
|
|
|
2021-04-13 14:54:07 -04:00
|
|
|
// Set extra options for non-Nanite meshes
|
2022-09-27 02:14:48 -04:00
|
|
|
if (!bForNanite)
|
2021-04-13 14:54:07 -04:00
|
|
|
{
|
|
|
|
|
ComputeNTBsOptions |= BuildSettings->bRemoveDegenerates ? EComputeNTBsFlags::IgnoreDegenerateTriangles : EComputeNTBsFlags::None;
|
2022-09-27 02:14:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bNeedTangents)
|
|
|
|
|
{
|
2021-04-13 14:54:07 -04:00
|
|
|
ComputeNTBsOptions |= BuildSettings->bRecomputeTangents ? EComputeNTBsFlags::Tangents : EComputeNTBsFlags::None;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-03 15:58:34 -04:00
|
|
|
// Compute any missing normals or tangents.
|
2020-10-26 13:09:34 -04:00
|
|
|
FStaticMeshOperations::ComputeTangentsAndNormals(RenderMeshDescription, ComputeNTBsOptions);
|
2017-09-22 17:58:06 -04:00
|
|
|
|
2020-10-26 13:09:34 -04:00
|
|
|
if (BuildSettings->bGenerateLightmapUVs && VertexInstanceArray.Num() > 0)
|
2017-09-15 11:19:07 -04:00
|
|
|
{
|
2021-11-18 14:37:34 -05:00
|
|
|
TVertexInstanceAttributesRef<FVector2f> VertexInstanceUVs = Attributes.GetVertexInstanceUVs();
|
First pass of MeshDescription API and format refactor.
- Removed hardcoded element type arrays (Vertices, Edges, Triangles etc.). Mesh element types can now be arbitrarily added, with any number of channels.
- Mesh element containers have a much leaner format; instead of sparse arrays, they are now represented by a simple bitarray, determining whether an index is used or not. Consequently, mesh topology is now entirely described with the attribute system, e.g. edge start and end vertices, triangle vertices, etc.
- Support added for attributes of arbitrary dimensions, e.g. float[4] or int[2].
- Support added for attributes which index into another mesh element container.
- Added FMeshElementIndexer: this is an efficient container for maintaining backward references from one element type to another; for example, edges have an attribute specifying which vertices are at each end (an attribute of type FVertexID[2]). With an indexer, it is possible to look up which edges contain a given vertex, even though this is not explicitly stored. Indexers are designed to do minimal allocations and update lazily and in batch when necessary.
- Added support for preserving UV topology in static meshes. UVs are now a first-class element type which may be indexed directly from triangles.
- Added the facility to access the underlying array in an attribute array directly.
- Triangles now directly reference their vertex, edge and UV IDs. Vertex instances are to be deprecated.
- Changed various systems to be triangle-centric rather than polygon-centric, as this is faster. Triangles are presumed to be the elementary face type in a MeshDescription, even if polygons are still supported. The concept of polygons will be somewhat shifted to mean a group of triangles which should be treated collectively for editing purposes.
- Optimised normal/tangent generation and FBX import.
- Deprecated EditableMesh, MeshEditor and StaticMeshEditorExtension plugins - these are to be removed, but they still have certain hooks in place which need removing.
#rb
[CL 13568702 by Richard TalbotWatkin in ue5-main branch]
2020-05-28 10:56:57 -04:00
|
|
|
int32 NumIndices = VertexInstanceUVs.GetNumChannels();
|
2017-12-28 17:15:00 -05:00
|
|
|
//Verify the src light map channel
|
|
|
|
|
if (BuildSettings->SrcLightmapIndex >= NumIndices)
|
2017-09-22 17:58:06 -04:00
|
|
|
{
|
|
|
|
|
BuildSettings->SrcLightmapIndex = 0;
|
|
|
|
|
}
|
2017-12-28 17:15:00 -05:00
|
|
|
//Verify the destination light map channel
|
|
|
|
|
if (BuildSettings->DstLightmapIndex >= NumIndices)
|
|
|
|
|
{
|
|
|
|
|
//Make sure we do not add illegal UV Channel index
|
|
|
|
|
if (BuildSettings->DstLightmapIndex >= MAX_MESH_TEXTURE_COORDS_MD)
|
|
|
|
|
{
|
|
|
|
|
BuildSettings->DstLightmapIndex = MAX_MESH_TEXTURE_COORDS_MD - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Add some unused UVChannel to the mesh description for the lightmapUVs
|
First pass of MeshDescription API and format refactor.
- Removed hardcoded element type arrays (Vertices, Edges, Triangles etc.). Mesh element types can now be arbitrarily added, with any number of channels.
- Mesh element containers have a much leaner format; instead of sparse arrays, they are now represented by a simple bitarray, determining whether an index is used or not. Consequently, mesh topology is now entirely described with the attribute system, e.g. edge start and end vertices, triangle vertices, etc.
- Support added for attributes of arbitrary dimensions, e.g. float[4] or int[2].
- Support added for attributes which index into another mesh element container.
- Added FMeshElementIndexer: this is an efficient container for maintaining backward references from one element type to another; for example, edges have an attribute specifying which vertices are at each end (an attribute of type FVertexID[2]). With an indexer, it is possible to look up which edges contain a given vertex, even though this is not explicitly stored. Indexers are designed to do minimal allocations and update lazily and in batch when necessary.
- Added support for preserving UV topology in static meshes. UVs are now a first-class element type which may be indexed directly from triangles.
- Added the facility to access the underlying array in an attribute array directly.
- Triangles now directly reference their vertex, edge and UV IDs. Vertex instances are to be deprecated.
- Changed various systems to be triangle-centric rather than polygon-centric, as this is faster. Triangles are presumed to be the elementary face type in a MeshDescription, even if polygons are still supported. The concept of polygons will be somewhat shifted to mean a group of triangles which should be treated collectively for editing purposes.
- Optimised normal/tangent generation and FBX import.
- Deprecated EditableMesh, MeshEditor and StaticMeshEditorExtension plugins - these are to be removed, but they still have certain hooks in place which need removing.
#rb
[CL 13568702 by Richard TalbotWatkin in ue5-main branch]
2020-05-28 10:56:57 -04:00
|
|
|
VertexInstanceUVs.SetNumChannels(BuildSettings->DstLightmapIndex + 1);
|
2017-12-28 17:15:00 -05:00
|
|
|
BuildSettings->DstLightmapIndex = NumIndices;
|
|
|
|
|
}
|
2020-01-23 16:28:59 -05:00
|
|
|
FStaticMeshOperations::CreateLightMapUVLayout(RenderMeshDescription,
|
2018-02-22 11:20:51 -05:00
|
|
|
BuildSettings->SrcLightmapIndex,
|
|
|
|
|
BuildSettings->DstLightmapIndex,
|
|
|
|
|
BuildSettings->MinLightmapResolution,
|
2020-10-22 19:19:16 -04:00
|
|
|
(ELightmapUVVersion)StaticMesh->GetLightmapUVVersion(),
|
2018-02-22 11:20:51 -05:00
|
|
|
OverlappingCorners);
|
2017-09-15 11:19:07 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 05:49:40 -04:00
|
|
|
void FMeshDescriptionHelper::ReduceLOD(const FMeshDescription& BaseMesh, FMeshDescription& DestMesh, const FMeshReductionSettings& ReductionSettings, const FOverlappingCorners& InOverlappingCorners, float &OutMaxDeviation)
|
2017-11-01 18:22:05 -04:00
|
|
|
{
|
|
|
|
|
IMeshReductionManagerModule& MeshReductionModule = FModuleManager::Get().LoadModuleChecked<IMeshReductionManagerModule>("MeshReductionInterface");
|
|
|
|
|
IMeshReduction* MeshReduction = MeshReductionModule.GetStaticMeshReductionInterface();
|
|
|
|
|
|
2018-11-14 19:05:13 -05:00
|
|
|
|
|
|
|
|
if (!MeshReduction)
|
2017-11-01 18:22:05 -04:00
|
|
|
{
|
2018-11-14 19:05:13 -05:00
|
|
|
// no reduction possible
|
|
|
|
|
OutMaxDeviation = 0.f;
|
2017-11-01 18:22:05 -04:00
|
|
|
return;
|
|
|
|
|
}
|
2018-11-14 19:05:13 -05:00
|
|
|
|
2018-06-16 10:22:53 -04:00
|
|
|
OutMaxDeviation = ReductionSettings.MaxDeviation;
|
|
|
|
|
MeshReduction->ReduceMeshDescription(DestMesh, OutMaxDeviation, BaseMesh, InOverlappingCorners, ReductionSettings);
|
2017-11-01 18:22:05 -04:00
|
|
|
}
|
|
|
|
|
|
2018-06-07 16:22:56 -04:00
|
|
|
void FMeshDescriptionHelper::FindOverlappingCorners(const FMeshDescription& MeshDescription, float ComparisonThreshold)
|
2017-11-01 18:22:05 -04:00
|
|
|
{
|
2020-01-23 16:28:59 -05:00
|
|
|
FStaticMeshOperations::FindOverlappingCorners(OverlappingCorners, MeshDescription, ComparisonThreshold);
|
2017-11-01 18:22:05 -04:00
|
|
|
}
|
|
|
|
|
|