2019-12-26 14:45:42 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-10-01 20:41:42 -04:00
# include "StaticMeshOperations.h"
2020-01-23 16:28:59 -05:00
# include "StaticMeshAttributes.h"
# include "UVMapSettings.h"
# include "Async/ParallelFor.h"
# include "LayoutUV.h"
# include "MeshUtilitiesCommon.h"
# include "Misc/SecureHash.h"
# include "OverlappingCorners.h"
# include "RawMesh.h"
2023-06-15 14:13:53 -04:00
# include "Modules/ModuleManager.h"
# if WITH_EDITOR
# include "IGeometryProcessingInterfacesModule.h"
# include "GeometryProcessingInterfaces/MeshAutoUV.h"
# endif
2020-01-23 16:28:59 -05:00
# if WITH_MIKKTSPACE
# include "mikktspace.h"
# endif //WITH_MIKKTSPACE
DEFINE_LOG_CATEGORY ( LogStaticMeshOperations ) ;
# define LOCTEXT_NAMESPACE "StaticMeshOperations"
2019-10-01 20:41:42 -04:00
static bool GetPolygonTangentsAndNormals ( FMeshDescription & MeshDescription ,
FPolygonID PolygonID ,
float ComparisonThreshold ,
2021-05-05 15:07:25 -04:00
TVertexAttributesConstRef < const FVector3f > VertexPositions ,
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesConstRef < const FVector2f > VertexUVs ,
2021-05-05 15:07:25 -04:00
TPolygonAttributesRef < FVector3f > PolygonNormals ,
TPolygonAttributesRef < FVector3f > PolygonTangents ,
TPolygonAttributesRef < FVector3f > PolygonBinormals ,
TPolygonAttributesRef < FVector3f > PolygonCenters )
2019-10-01 20:41:42 -04:00
{
bool bValidNTBs = true ;
2020-01-23 16:28:59 -05:00
// Calculate the tangent basis for the polygon, based on the average of all constituent triangles
2021-11-18 14:37:34 -05:00
FVector3f Normal ( FVector3f : : ZeroVector ) ;
FVector3f Tangent ( FVector3f : : ZeroVector ) ;
FVector3f Binormal ( FVector3f : : ZeroVector ) ;
FVector3f Center ( FVector3f : : ZeroVector ) ;
2020-01-23 16:28:59 -05:00
2019-10-01 20:41:42 -04:00
// Calculate the center of this polygon
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
TArray < FVertexInstanceID , TInlineAllocator < 4 > > VertexInstanceIDs = MeshDescription . GetPolygonVertexInstances < TInlineAllocator < 4 > > ( PolygonID ) ;
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID & VertexInstanceID : VertexInstanceIDs )
2019-10-01 20:41:42 -04:00
{
Center + = VertexPositions [ MeshDescription . GetVertexInstanceVertex ( VertexInstanceID ) ] ;
}
Center / = float ( VertexInstanceIDs . Num ( ) ) ;
2022-08-22 11:16:01 -04:00
// GetSafeNormal compare the squareSum to the tolerance.
const float SquareComparisonThreshold = FMath : : Max ( ComparisonThreshold * ComparisonThreshold , MIN_flt ) ;
2022-01-06 16:44:09 +00:00
for ( const FTriangleID & TriangleID : MeshDescription . GetPolygonTriangles ( PolygonID ) )
2019-10-01 20:41:42 -04:00
{
TArrayView < const FVertexInstanceID > TriangleVertexInstances = MeshDescription . GetTriangleVertexInstances ( TriangleID ) ;
const FVertexID VertexID0 = MeshDescription . GetVertexInstanceVertex ( TriangleVertexInstances [ 0 ] ) ;
const FVertexID VertexID1 = MeshDescription . GetVertexInstanceVertex ( TriangleVertexInstances [ 1 ] ) ;
const FVertexID VertexID2 = MeshDescription . GetVertexInstanceVertex ( TriangleVertexInstances [ 2 ] ) ;
2021-11-18 14:37:34 -05:00
const FVector3f Position0 = VertexPositions [ VertexID0 ] ;
2023-02-27 16:41:38 -05:00
const FVector3f DPosition1 = VertexPositions [ VertexID1 ] - Position0 ;
const FVector3f DPosition2 = VertexPositions [ VertexID2 ] - Position0 ;
2019-10-01 20:41:42 -04:00
2021-11-18 14:37:34 -05:00
const FVector2f UV0 = VertexUVs [ TriangleVertexInstances [ 0 ] ] ;
const FVector2f DUV1 = VertexUVs [ TriangleVertexInstances [ 1 ] ] - UV0 ;
const FVector2f DUV2 = VertexUVs [ TriangleVertexInstances [ 2 ] ] - UV0 ;
2019-10-01 20:41:42 -04:00
// We have a left-handed coordinate system, but a counter-clockwise winding order
// Hence normal calculation has to take the triangle vectors cross product in reverse.
2022-08-22 11:16:01 -04:00
FVector3f TmpNormal = FVector3f : : CrossProduct ( DPosition2 , DPosition1 ) . GetSafeNormal ( SquareComparisonThreshold ) ;
2020-01-23 16:28:59 -05:00
if ( ! TmpNormal . IsNearlyZero ( ComparisonThreshold ) )
2019-10-01 20:41:42 -04:00
{
2021-11-18 14:37:34 -05:00
FMatrix44f ParameterToLocal (
2020-01-23 16:28:59 -05:00
DPosition1 ,
DPosition2 ,
Position0 ,
2021-11-18 14:37:34 -05:00
FVector3f : : ZeroVector
2020-01-23 16:28:59 -05:00
) ;
2019-10-01 20:41:42 -04:00
2021-11-18 14:37:34 -05:00
FMatrix44f ParameterToTexture (
FPlane4f ( DUV1 . X , DUV1 . Y , 0 , 0 ) ,
FPlane4f ( DUV2 . X , DUV2 . Y , 0 , 0 ) ,
FPlane4f ( UV0 . X , UV0 . Y , 1 , 0 ) ,
FPlane4f ( 0 , 0 , 0 , 1 )
2020-01-23 16:28:59 -05:00
) ;
// Use InverseSlow to catch singular matrices. Inverse can miss this sometimes.
2021-11-18 14:37:34 -05:00
const FMatrix44f TextureToLocal = ParameterToTexture . Inverse ( ) * ParameterToLocal ;
2020-01-23 16:28:59 -05:00
2021-11-18 14:37:34 -05:00
FVector3f TmpTangent = TextureToLocal . TransformVector ( FVector3f ( 1 , 0 , 0 ) ) . GetSafeNormal ( ) ;
FVector3f TmpBinormal = TextureToLocal . TransformVector ( FVector3f ( 0 , 1 , 0 ) ) . GetSafeNormal ( ) ;
FVector3f : : CreateOrthonormalBasis ( TmpTangent , TmpBinormal , TmpNormal ) ;
2020-01-23 16:28:59 -05:00
if ( TmpTangent . IsNearlyZero ( ) | | TmpTangent . ContainsNaN ( )
| | TmpBinormal . IsNearlyZero ( ) | | TmpBinormal . ContainsNaN ( ) )
{
2021-11-18 14:37:34 -05:00
TmpTangent = FVector3f : : ZeroVector ;
TmpBinormal = FVector3f : : ZeroVector ;
2020-01-23 16:28:59 -05:00
bValidNTBs = false ;
}
if ( TmpNormal . IsNearlyZero ( ) | | TmpNormal . ContainsNaN ( ) )
{
2021-11-18 14:37:34 -05:00
TmpNormal = FVector3f : : ZeroVector ;
2020-01-23 16:28:59 -05:00
bValidNTBs = false ;
}
Normal + = TmpNormal ;
Tangent + = TmpTangent ;
Binormal + = TmpBinormal ;
2019-10-01 20:41:42 -04:00
}
else
{
2020-01-23 16:28:59 -05:00
//This will force a recompute of the normals and tangents
2021-11-18 14:37:34 -05:00
Normal = FVector3f : : ZeroVector ;
Tangent = FVector3f : : ZeroVector ;
Binormal = FVector3f : : ZeroVector ;
2020-01-23 16:28:59 -05:00
2019-10-01 20:41:42 -04:00
// The polygon is degenerated
bValidNTBs = false ;
}
}
PolygonNormals [ PolygonID ] = Normal . GetSafeNormal ( ) ;
PolygonTangents [ PolygonID ] = Tangent . GetSafeNormal ( ) ;
PolygonBinormals [ PolygonID ] = Binormal . GetSafeNormal ( ) ;
PolygonCenters [ PolygonID ] = Center ;
return bValidNTBs ;
}
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
2019-11-06 18:17:34 -05:00
void FStaticMeshOperations : : ComputePolygonTangentsAndNormals ( FMeshDescription & MeshDescription , float ComparisonThreshold )
{
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
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2020-09-24 00:43:27 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : ComputePolygonTangentsAndNormals_Selection ) ;
2020-01-23 16:28:59 -05:00
2019-11-06 18:17:34 -05:00
FStaticMeshAttributes Attributes ( MeshDescription ) ;
Attributes . RegisterPolygonNormalAndTangentAttributes ( ) ;
2020-01-23 16:28:59 -05:00
TArray < FPolygonID > PolygonIDs ;
PolygonIDs . Reserve ( MeshDescription . Polygons ( ) . Num ( ) ) ;
2022-01-06 16:44:09 +00:00
for ( const FPolygonID Polygon : MeshDescription . Polygons ( ) . GetElementIDs ( ) )
2019-11-06 18:17:34 -05:00
{
2020-01-23 16:28:59 -05:00
PolygonIDs . Add ( Polygon ) ;
}
// Split work in batch to reduce call overhead
const int32 BatchSize = 8 * 1024 ;
const int32 BatchCount = 1 + PolygonIDs . Num ( ) / BatchSize ;
ParallelFor ( BatchCount ,
[ & PolygonIDs , & BatchSize , & ComparisonThreshold , & MeshDescription , & Attributes ] ( int32 BatchIndex )
2019-11-06 18:17:34 -05:00
{
2021-05-05 15:07:25 -04:00
TVertexAttributesConstRef < FVector3f > VertexPositions = Attributes . GetVertexPositions ( ) ;
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesConstRef < FVector2f > VertexUVs = Attributes . GetVertexInstanceUVs ( ) ;
2021-05-05 15:07:25 -04:00
TPolygonAttributesRef < FVector3f > PolygonNormals = Attributes . GetPolygonNormals ( ) ;
TPolygonAttributesRef < FVector3f > PolygonTangents = Attributes . GetPolygonTangents ( ) ;
TPolygonAttributesRef < FVector3f > PolygonBinormals = Attributes . GetPolygonBinormals ( ) ;
TPolygonAttributesRef < FVector3f > PolygonCenters = Attributes . GetPolygonCenters ( ) ;
2020-01-23 16:28:59 -05:00
FVertexInstanceArray & VertexInstanceArray = MeshDescription . VertexInstances ( ) ;
FVertexArray & VertexArray = MeshDescription . Vertices ( ) ;
FPolygonArray & PolygonArray = MeshDescription . Polygons ( ) ;
int32 Indice = BatchIndex * BatchSize ;
int32 LastIndice = FMath : : Min ( Indice + BatchSize , PolygonIDs . Num ( ) ) ;
for ( ; Indice < LastIndice ; + + Indice )
{
const FPolygonID PolygonID = PolygonIDs [ Indice ] ;
if ( ! PolygonNormals [ PolygonID ] . IsNearlyZero ( ) )
{
//By pass normal calculation if its already done
continue ;
}
GetPolygonTangentsAndNormals ( MeshDescription , PolygonID , ComparisonThreshold , VertexPositions , VertexUVs , PolygonNormals , PolygonTangents , PolygonBinormals , PolygonCenters ) ;
}
2019-11-06 18:17:34 -05:00
}
2020-01-23 16:28:59 -05:00
) ;
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
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2019-10-01 20:41:42 -04:00
}
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
2024-03-04 21:06:34 -05:00
static TTuple < FVector3f , FVector3f , FVector3f > GetTriangleTangentsAndNormalsWithUV ( float ComparisonThreshold , TArrayView < const FVector3f > VertexPositions , TArrayView < const FVector2D > VertexUVs )
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
{
2022-08-22 11:16:01 -04:00
// GetSafeNormal compare the squareSum to the tolerance.
const float SquareComparisonThreshold = FMath : : Max ( ComparisonThreshold * ComparisonThreshold , MIN_flt ) ;
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
2021-11-18 14:37:34 -05:00
const FVector3f Position0 = VertexPositions [ 0 ] ;
2023-02-11 12:51:08 -05:00
// If the positions deltas are too small, we get a zero vector out.
2023-02-27 16:41:38 -05:00
const FVector3f DPosition1 = VertexPositions [ 1 ] - Position0 ;
const FVector3f DPosition2 = VertexPositions [ 2 ] - Position0 ;
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
2022-02-02 01:47:07 -05:00
const FVector2f UV0 = FVector2f ( VertexUVs [ 0 ] ) ;
const FVector2f DUV1 = FVector2f ( VertexUVs [ 1 ] ) - UV0 ;
const FVector2f DUV2 = FVector2f ( VertexUVs [ 2 ] ) - UV0 ;
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
// We have a left-handed coordinate system, but a counter-clockwise winding order
// Hence normal calculation has to take the triangle vectors cross product in reverse.
2023-02-11 12:51:08 -05:00
// If we got a zero vector out above, then this is also zero
2022-08-22 11:16:01 -04:00
FVector3f Normal = FVector3f : : CrossProduct ( DPosition2 , DPosition1 ) . GetSafeNormal ( SquareComparisonThreshold ) ;
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
if ( ! Normal . IsNearlyZero ( ComparisonThreshold ) )
{
2021-11-18 14:37:34 -05:00
FMatrix44f ParameterToLocal (
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
DPosition1 ,
DPosition2 ,
Position0 ,
2021-11-18 14:37:34 -05:00
FVector3f : : ZeroVector
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
) ;
2021-11-18 14:37:34 -05:00
FMatrix44f ParameterToTexture (
FPlane4f ( DUV1 . X , DUV1 . Y , 0 , 0 ) ,
FPlane4f ( DUV2 . X , DUV2 . Y , 0 , 0 ) ,
FPlane4f ( UV0 . X , UV0 . Y , 1 , 0 ) ,
FPlane4f ( 0 , 0 , 0 , 1 )
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
) ;
// Use InverseSlow to catch singular matrices. Inverse can miss this sometimes.
2021-11-18 14:37:34 -05:00
const FMatrix44f TextureToLocal = ParameterToTexture . Inverse ( ) * ParameterToLocal ;
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
2021-11-18 14:37:34 -05:00
FVector3f Tangent = TextureToLocal . TransformVector ( FVector3f ( 1 , 0 , 0 ) ) . GetSafeNormal ( ) ;
FVector3f Binormal = TextureToLocal . TransformVector ( FVector3f ( 0 , 1 , 0 ) ) . GetSafeNormal ( ) ;
FVector3f : : CreateOrthonormalBasis ( Tangent , Binormal , Normal ) ;
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
if ( Tangent . IsNearlyZero ( ) | | Tangent . ContainsNaN ( )
| | Binormal . IsNearlyZero ( ) | | Binormal . ContainsNaN ( ) )
{
2021-11-18 14:37:34 -05:00
Tangent = FVector3f : : ZeroVector ;
Binormal = FVector3f : : ZeroVector ;
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
}
if ( Normal . IsNearlyZero ( ) | | Normal . ContainsNaN ( ) )
{
2021-11-18 14:37:34 -05:00
Normal = FVector3f : : ZeroVector ;
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
}
return MakeTuple ( Normal . GetSafeNormal ( ) , Tangent . GetSafeNormal ( ) , Binormal . GetSafeNormal ( ) ) ;
}
else
{
// This will force a recompute of the normals and tangents
2021-11-18 14:37:34 -05:00
return MakeTuple ( FVector3f : : ZeroVector , FVector3f : : ZeroVector , FVector3f : : ZeroVector ) ;
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
}
}
2024-03-04 21:06:34 -05:00
// Create a normal using the triangle plane, but use the Duff & Frisvad algorithm (see Duff 2017 in JCGT) to construct a consistent tangent from a
// single vector.
static TTuple < FVector3f , FVector3f , FVector3f > GetTriangleTangentsAndNormalsWithNoUVs ( float ComparisonThreshold , TArrayView < const FVector3f > VertexPositions )
{
// GetSafeNormal compare the squareSum to the tolerance.
const float SquareComparisonThreshold = FMath : : Max ( ComparisonThreshold * ComparisonThreshold , MIN_flt ) ;
const FVector3f Position0 = VertexPositions [ 0 ] ;
// If the positions deltas are too small, we get a zero vector out.
const FVector3f DPosition1 = VertexPositions [ 1 ] - Position0 ;
const FVector3f DPosition2 = VertexPositions [ 2 ] - Position0 ;
// We have a left-handed coordinate system, but a counter-clockwise winding order
// Hence normal calculation has to take the triangle vectors cross product in reverse.
// If we got a zero vector out above, then this is also zero
FVector3f Normal = FVector3f : : CrossProduct ( DPosition2 , DPosition1 ) . GetSafeNormal ( SquareComparisonThreshold ) ;
if ( ! Normal . Normalize ( ComparisonThreshold ) )
{
return MakeTuple ( FVector3f : : ZeroVector , FVector3f : : ZeroVector , FVector3f : : ZeroVector ) ;
}
FVector3f Tangent , Binormal ;
if ( Normal . Z < 0.0f )
{
const float A = 1.0f / ( 1.0f - Normal . Z ) ;
const float B = Normal . X * Normal . Y * A ;
Tangent = FVector3f ( 1.0f - Normal . X * Normal . X * A , - B , Normal . X ) ;
Binormal = FVector3f ( B , Normal . Y * Normal . Y * A - 1.0f , - Normal . Y ) ;
}
else
{
const float A = 1.0f / ( 1.0f + Normal . Z ) ;
const float B = - Normal . X * Normal . Y * A ;
Tangent = FVector3f ( 1.0f - Normal . X * Normal . X * A , B , - Normal . X ) ;
Binormal = FVector3f ( B , 1.0f - Normal . Y * Normal . Y * A , - Normal . Y ) ;
}
// The above algorithm guarantees orthogonality and normalization of the tangent & binormal if the normal vector is already normalized.
return MakeTuple ( Normal , Tangent , Binormal ) ;
}
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
2023-02-11 12:51:08 -05:00
void FStaticMeshOperations : : ComputeTriangleTangentsAndNormals ( FMeshDescription & MeshDescription , float ComparisonThreshold , const TCHAR * DebugName )
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
{
2021-01-19 06:29:15 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : ComputeTriangleTangentsAndNormals_Selection ) ;
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
FStaticMeshAttributes Attributes ( MeshDescription ) ;
Attributes . RegisterTriangleNormalAndTangentAttributes ( ) ;
// Check that the mesh description is compact
const int32 NumTriangles = MeshDescription . Triangles ( ) . Num ( ) ;
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 ( MeshDescription . NeedsCompact ( ) )
2021-03-02 15:34:39 -04:00
{
FElementIDRemappings Remappings ;
MeshDescription . Compact ( Remappings ) ;
}
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
// Split work in batch to reduce call overhead
const int32 BatchSize = 8 * 1024 ;
const int32 BatchCount = ( NumTriangles + BatchSize - 1 ) / BatchSize ;
2022-02-23 19:25:03 -05:00
ParallelFor ( TEXT ( " ComputeTriangleTangentsAndNormals.PF " ) , BatchCount , 1 ,
2023-02-11 12:51:08 -05:00
[ BatchSize , ComparisonThreshold , NumTriangles , & Attributes , DebugName ] ( int32 BatchIndex )
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
{
2021-05-05 15:07:25 -04:00
TArrayView < const FVector3f > VertexPositions = Attributes . GetVertexPositions ( ) . GetRawArray ( ) ;
2024-03-04 21:06:34 -05:00
TArrayView < const FVector2f > VertexUVs ;
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
TArrayView < const FVertexID > TriangleVertexIDs = Attributes . GetTriangleVertexIndices ( ) . GetRawArray ( ) ;
TArrayView < const FVertexInstanceID > TriangleVertexInstanceIDs = Attributes . GetTriangleVertexInstanceIndices ( ) . GetRawArray ( ) ;
2021-05-05 15:07:25 -04:00
TArrayView < FVector3f > TriangleNormals = Attributes . GetTriangleNormals ( ) . GetRawArray ( ) ;
TArrayView < FVector3f > TriangleTangents = Attributes . GetTriangleTangents ( ) . GetRawArray ( ) ;
TArrayView < FVector3f > TriangleBinormals = Attributes . GetTriangleBinormals ( ) . GetRawArray ( ) ;
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
2024-03-04 21:06:34 -05:00
if ( Attributes . GetVertexInstanceUVs ( ) . GetNumChannels ( ) > 0 )
{
VertexUVs = Attributes . GetVertexInstanceUVs ( ) . GetRawArray ( 0 ) ;
}
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 StartIndex = BatchIndex * BatchSize ;
int32 TriIndex = StartIndex * 3 ;
int32 EndIndex = FMath : : Min ( StartIndex + BatchSize , NumTriangles ) ;
for ( ; StartIndex < EndIndex ; + + StartIndex , TriIndex + = 3 )
{
if ( ! TriangleNormals [ StartIndex ] . IsNearlyZero ( ) )
{
// Bypass normal calculation if it's already done
continue ;
}
2021-05-05 15:07:25 -04:00
FVector3f TriangleVertexPositions [ 3 ] =
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
{
VertexPositions [ TriangleVertexIDs [ TriIndex ] ] ,
VertexPositions [ TriangleVertexIDs [ TriIndex + 1 ] ] ,
VertexPositions [ TriangleVertexIDs [ TriIndex + 2 ] ]
} ;
2023-02-11 12:51:08 -05:00
if ( TriangleVertexPositions [ 0 ] . ContainsNaN ( ) | |
TriangleVertexPositions [ 1 ] . ContainsNaN ( ) | |
TriangleVertexPositions [ 2 ] . ContainsNaN ( ) )
{
2024-03-04 21:06:34 -05:00
UE_CLOG ( DebugName ! = nullptr , LogStaticMeshOperations , Warning , TEXT ( " Static Mesh %s has NaNs in it's vertex positions! Triangle index %d -- using identity for tangent basis. " ) , DebugName , StartIndex ) ;
2023-02-11 12:51:08 -05:00
TriangleNormals [ StartIndex ] = FVector3f ( 1 , 0 , 0 ) ;
TriangleTangents [ StartIndex ] = FVector3f ( 0 , 1 , 0 ) ;
TriangleBinormals [ StartIndex ] = FVector3f ( 0 , 0 , 1 ) ;
continue ;
}
2024-03-04 21:06:34 -05:00
TTuple < FVector3f , FVector3f , FVector3f > Result ;
if ( ! VertexUVs . IsEmpty ( ) )
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
{
2024-03-04 21:06:34 -05:00
FVector2D TriangleUVs [ 3 ] =
{
FVector2D ( VertexUVs [ TriangleVertexInstanceIDs [ TriIndex ] ] ) ,
FVector2D ( VertexUVs [ TriangleVertexInstanceIDs [ TriIndex + 1 ] ] ) ,
FVector2D ( VertexUVs [ TriangleVertexInstanceIDs [ TriIndex + 2 ] ] )
} ;
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
2024-03-04 21:06:34 -05:00
if ( TriangleUVs [ 0 ] . ContainsNaN ( ) | |
TriangleUVs [ 1 ] . ContainsNaN ( ) | |
TriangleUVs [ 2 ] . ContainsNaN ( ) )
{
UE_CLOG ( DebugName ! = nullptr , LogStaticMeshOperations , Warning , TEXT ( " Static Mesh %s has NaNs in it's vertex uvs! Triangle index %d -- using identity for tangent basis. " ) , DebugName , StartIndex ) ;
TriangleNormals [ StartIndex ] = FVector3f ( 1 , 0 , 0 ) ;
TriangleTangents [ StartIndex ] = FVector3f ( 0 , 1 , 0 ) ;
TriangleBinormals [ StartIndex ] = FVector3f ( 0 , 0 , 1 ) ;
continue ;
}
Result = GetTriangleTangentsAndNormalsWithUV ( ComparisonThreshold , TriangleVertexPositions , TriangleUVs ) ;
}
else
{
Result = GetTriangleTangentsAndNormalsWithNoUVs ( ComparisonThreshold , TriangleVertexPositions ) ;
2023-02-11 12:51:08 -05:00
}
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
TriangleNormals [ StartIndex ] = Result . Get < 0 > ( ) ;
TriangleTangents [ StartIndex ] = Result . Get < 1 > ( ) ;
TriangleBinormals [ StartIndex ] = Result . Get < 2 > ( ) ;
2024-03-04 21:06:34 -05:00
}
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
}
) ;
}
2019-10-01 20:41:42 -04:00
void FStaticMeshOperations : : DetermineEdgeHardnessesFromVertexInstanceNormals ( FMeshDescription & MeshDescription , float Tolerance )
{
FStaticMeshAttributes Attributes ( MeshDescription ) ;
2021-05-05 15:07:25 -04:00
TVertexInstanceAttributesRef < const FVector3f > VertexNormals = Attributes . GetVertexInstanceNormals ( ) ;
2019-10-01 20:41:42 -04:00
TEdgeAttributesRef < bool > EdgeHardnesses = Attributes . GetEdgeHardnesses ( ) ;
// Holds unique vertex instance IDs for a given edge vertex
TArray < FVertexInstanceID > UniqueVertexInstanceIDs ;
for ( const FEdgeID EdgeID : MeshDescription . Edges ( ) . GetElementIDs ( ) )
{
// Get list of polygons connected to this edge
TArray < FPolygonID , TInlineAllocator < 2 > > ConnectedPolygonIDs = MeshDescription . GetEdgeConnectedPolygons < TInlineAllocator < 2 > > ( EdgeID ) ;
if ( ConnectedPolygonIDs . Num ( ) = = 0 )
{
// What does it mean if an edge has no connected polygons? For now we just skip it
continue ;
}
// Assume by default that the edge is soft - but as soon as any vertex instance belonging to a connected polygon
// has a distinct normal from the others (within the given tolerance), we mark it as hard.
// The exception is if an edge has exactly one connected polygon: in this case we automatically deem it a hard edge.
bool bEdgeIsHard = ( ConnectedPolygonIDs . Num ( ) = = 1 ) ;
// Examine vertices on each end of the edge, if we haven't yet identified it as 'hard'
for ( int32 VertexIndex = 0 ; ! bEdgeIsHard & & VertexIndex < 2 ; + + VertexIndex )
{
const FVertexID VertexID = MeshDescription . GetEdgeVertex ( EdgeID , VertexIndex ) ;
const int32 ReservedElements = 4 ;
UniqueVertexInstanceIDs . Reset ( ReservedElements ) ;
// Get a list of all vertex instances for this vertex which form part of any polygon connected to the edge
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID & VertexInstanceID : MeshDescription . GetVertexVertexInstanceIDs ( VertexID ) )
2019-10-01 20:41:42 -04:00
{
2022-01-06 16:44:09 +00:00
for ( const FPolygonID & PolygonID : MeshDescription . GetVertexInstanceConnectedPolygons < TInlineAllocator < 8 > > ( VertexInstanceID ) )
2019-10-01 20:41:42 -04:00
{
if ( ConnectedPolygonIDs . Contains ( PolygonID ) )
{
UniqueVertexInstanceIDs . AddUnique ( VertexInstanceID ) ;
break ;
}
}
}
check ( UniqueVertexInstanceIDs . Num ( ) > 0 ) ;
// First unique vertex instance is used as a reference against which the others are compared.
// (not a perfect approach: really the 'median' should be used as a reference)
2021-11-18 14:37:34 -05:00
const FVector3f ReferenceNormal = VertexNormals [ UniqueVertexInstanceIDs [ 0 ] ] ;
2019-10-01 20:41:42 -04:00
for ( int32 Index = 1 ; Index < UniqueVertexInstanceIDs . Num ( ) ; + + Index )
{
if ( ! VertexNormals [ UniqueVertexInstanceIDs [ Index ] ] . Equals ( ReferenceNormal , Tolerance ) )
{
bEdgeIsHard = true ;
break ;
}
}
}
EdgeHardnesses [ EdgeID ] = bEdgeIsHard ;
}
}
2020-01-23 16:28:59 -05:00
//////////////////
struct FVertexInfo
{
FVertexInfo ( )
{
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
TriangleID = INDEX_NONE ;
VertexInstanceID = INDEX_NONE ;
2022-02-02 01:47:07 -05:00
UVs = FVector2f ( 0.0f , 0.0f ) ;
2020-01-23 16:28:59 -05:00
}
FTriangleID TriangleID ;
FVertexInstanceID VertexInstanceID ;
2021-11-18 14:37:34 -05:00
FVector2f UVs ;
2020-01-23 16:28:59 -05:00
//Most of the time a edge has two triangles
TArray < FEdgeID , TInlineAllocator < 2 > > EdgeIDs ;
} ;
/** Helper struct for building acceleration structures. */
namespace MeshDescriptionOperationNamespace
{
struct FIndexAndZ
{
float Z ;
int32 Index ;
2021-05-05 15:07:25 -04:00
const FVector3f * OriginalVector ;
2020-01-23 16:28:59 -05:00
/** Default constructor. */
FIndexAndZ ( ) { }
/** Initialization constructor. */
2021-05-05 15:07:25 -04:00
FIndexAndZ ( int32 InIndex , const FVector3f & V )
2020-01-23 16:28:59 -05:00
{
Z = 0.30f * V . X + 0.33f * V . Y + 0.37f * V . Z ;
Index = InIndex ;
OriginalVector = & V ;
}
} ;
/** Sorting function for vertex Z/index pairs. */
struct FCompareIndexAndZ
{
FORCEINLINE bool operator ( ) ( const FIndexAndZ & A , const FIndexAndZ & B ) const { return A . Z < B . Z ; }
} ;
}
void FStaticMeshOperations : : ConvertHardEdgesToSmoothGroup ( const FMeshDescription & SourceMeshDescription , TArray < uint32 > & FaceSmoothingMasks )
{
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : ConvertHardEdgesToSmoothGroup ) ;
TMap < FPolygonID , uint32 > PolygonSmoothGroup ;
PolygonSmoothGroup . Reserve ( SourceMeshDescription . Polygons ( ) . GetArraySize ( ) ) ;
TArray < bool > ConsumedPolygons ;
ConsumedPolygons . AddZeroed ( SourceMeshDescription . Polygons ( ) . GetArraySize ( ) ) ;
TMap < FPolygonID , uint32 > PolygonAvoidances ;
TEdgeAttributesConstRef < bool > EdgeHardnesses = SourceMeshDescription . EdgeAttributes ( ) . GetAttributesRef < bool > ( MeshAttribute : : Edge : : IsHard ) ;
int32 TriangleCount = 0 ;
TArray < FPolygonID > SoftEdgeNeigbors ;
TArray < FEdgeID > PolygonEdges ;
TArray < FPolygonID > EdgeConnectedPolygons ;
TArray < FPolygonID > ConnectedPolygons ;
TArray < FPolygonID > LastConnectedPolygons ;
for ( const FPolygonID PolygonID : SourceMeshDescription . Polygons ( ) . GetElementIDs ( ) )
{
2020-07-16 08:23:15 -04:00
TriangleCount + = SourceMeshDescription . GetPolygonTriangles ( PolygonID ) . Num ( ) ;
2020-01-23 16:28:59 -05:00
if ( ConsumedPolygons [ PolygonID . GetValue ( ) ] )
{
continue ;
}
ConnectedPolygons . Reset ( ) ;
LastConnectedPolygons . Reset ( ) ;
ConnectedPolygons . Add ( PolygonID ) ;
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
LastConnectedPolygons . Add ( INDEX_NONE ) ;
2020-01-23 16:28:59 -05:00
while ( ConnectedPolygons . Num ( ) > 0 )
{
check ( LastConnectedPolygons . Num ( ) = = ConnectedPolygons . Num ( ) ) ;
2024-01-19 16:41:35 -05:00
FPolygonID LastPolygonID = LastConnectedPolygons . Pop ( EAllowShrinking : : No ) ;
FPolygonID CurrentPolygonID = ConnectedPolygons . Pop ( EAllowShrinking : : No ) ;
2020-01-23 16:28:59 -05:00
if ( ConsumedPolygons [ CurrentPolygonID . GetValue ( ) ] )
{
continue ;
}
SoftEdgeNeigbors . Reset ( ) ;
uint32 & SmoothGroup = PolygonSmoothGroup . FindOrAdd ( CurrentPolygonID ) ;
uint32 AvoidSmoothGroup = 0 ;
uint32 NeighborSmoothGroup = 0 ;
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
const uint32 LastSmoothGroupValue = ( LastPolygonID = = INDEX_NONE ) ? 0 : PolygonSmoothGroup [ LastPolygonID ] ;
2020-01-23 16:28:59 -05:00
PolygonEdges . Reset ( ) ;
SourceMeshDescription . GetPolygonPerimeterEdges ( CurrentPolygonID , PolygonEdges ) ;
for ( const FEdgeID & EdgeID : PolygonEdges )
{
bool bIsHardEdge = EdgeHardnesses [ EdgeID ] ;
EdgeConnectedPolygons . Reset ( ) ;
SourceMeshDescription . GetEdgeConnectedPolygons ( EdgeID , EdgeConnectedPolygons ) ;
for ( const FPolygonID & EdgePolygonID : EdgeConnectedPolygons )
{
if ( EdgePolygonID = = CurrentPolygonID )
{
continue ;
}
uint32 SmoothValue = 0 ;
if ( PolygonSmoothGroup . Contains ( EdgePolygonID ) )
{
SmoothValue = PolygonSmoothGroup [ EdgePolygonID ] ;
}
if ( bIsHardEdge ) //Hard Edge
{
AvoidSmoothGroup | = SmoothValue ;
}
else
{
NeighborSmoothGroup | = SmoothValue ;
//Put all none hard edge polygon in the next iteration
if ( ! ConsumedPolygons [ EdgePolygonID . GetValue ( ) ] )
{
ConnectedPolygons . Add ( EdgePolygonID ) ;
LastConnectedPolygons . Add ( CurrentPolygonID ) ;
}
else
{
SoftEdgeNeigbors . Add ( EdgePolygonID ) ;
}
}
}
}
if ( AvoidSmoothGroup ! = 0 )
{
PolygonAvoidances . FindOrAdd ( CurrentPolygonID ) = AvoidSmoothGroup ;
//find neighbor avoidance
for ( FPolygonID & NeighborID : SoftEdgeNeigbors )
{
if ( ! PolygonAvoidances . Contains ( NeighborID ) )
{
continue ;
}
AvoidSmoothGroup | = PolygonAvoidances [ NeighborID ] ;
}
uint32 NewSmoothGroup = 1 ;
while ( ( NewSmoothGroup & AvoidSmoothGroup ) ! = 0 & & NewSmoothGroup < MAX_uint32 )
{
//Shift the smooth group
NewSmoothGroup = NewSmoothGroup < < 1 ;
}
SmoothGroup = NewSmoothGroup ;
//Apply to all neighboard
for ( FPolygonID & NeighborID : SoftEdgeNeigbors )
{
PolygonSmoothGroup [ NeighborID ] | = NewSmoothGroup ;
}
}
else if ( NeighborSmoothGroup ! = 0 )
{
SmoothGroup | = LastSmoothGroupValue | NeighborSmoothGroup ;
}
else
{
SmoothGroup = 1 ;
}
ConsumedPolygons [ CurrentPolygonID . GetValue ( ) ] = true ;
}
}
//Set the smooth group in the FaceSmoothingMasks parameter
check ( FaceSmoothingMasks . Num ( ) = = TriangleCount ) ;
int32 TriangleIndex = 0 ;
for ( const FPolygonID PolygonID : SourceMeshDescription . Polygons ( ) . GetElementIDs ( ) )
{
2022-01-06 16:44:09 +00:00
const uint32 PolygonSmoothValue = PolygonSmoothGroup [ PolygonID ] ;
for ( int32 i = 0 , Num = SourceMeshDescription . GetPolygonTriangles ( PolygonID ) . Num ( ) ; i < Num ; + + i )
2020-01-23 16:28:59 -05:00
{
FaceSmoothingMasks [ TriangleIndex + + ] = PolygonSmoothValue ;
}
}
}
void FStaticMeshOperations : : ConvertSmoothGroupToHardEdges ( const TArray < uint32 > & FaceSmoothingMasks , FMeshDescription & DestinationMeshDescription )
{
TEdgeAttributesRef < bool > EdgeHardnesses = DestinationMeshDescription . EdgeAttributes ( ) . GetAttributesRef < bool > ( MeshAttribute : : Edge : : IsHard ) ;
TArray < bool > ConsumedPolygons ;
ConsumedPolygons . AddZeroed ( DestinationMeshDescription . Polygons ( ) . Num ( ) ) ;
for ( const FPolygonID PolygonID : DestinationMeshDescription . Polygons ( ) . GetElementIDs ( ) )
{
if ( ConsumedPolygons [ PolygonID . GetValue ( ) ] )
{
continue ;
}
TArray < FPolygonID > ConnectedPolygons ;
ConnectedPolygons . Add ( PolygonID ) ;
while ( ConnectedPolygons . Num ( ) > 0 )
{
2024-01-19 16:41:35 -05:00
FPolygonID CurrentPolygonID = ConnectedPolygons . Pop ( EAllowShrinking : : No ) ;
2020-01-23 16:28:59 -05:00
int32 CurrentPolygonIDValue = CurrentPolygonID . GetValue ( ) ;
check ( FaceSmoothingMasks . IsValidIndex ( CurrentPolygonIDValue ) ) ;
const uint32 ReferenceSmoothGroup = FaceSmoothingMasks [ CurrentPolygonIDValue ] ;
TArray < FEdgeID > PolygonEdges ;
DestinationMeshDescription . GetPolygonPerimeterEdges ( CurrentPolygonID , PolygonEdges ) ;
for ( const FEdgeID & EdgeID : PolygonEdges )
{
const bool bIsHardEdge = EdgeHardnesses [ EdgeID ] ;
if ( bIsHardEdge )
{
continue ;
}
const TArray < FPolygonID > & EdgeConnectedPolygons = DestinationMeshDescription . GetEdgeConnectedPolygons ( EdgeID ) ;
for ( const FPolygonID & EdgePolygonID : EdgeConnectedPolygons )
{
int32 EdgePolygonIDValue = EdgePolygonID . GetValue ( ) ;
if ( EdgePolygonID = = CurrentPolygonID | | ConsumedPolygons [ EdgePolygonIDValue ] )
{
continue ;
}
check ( FaceSmoothingMasks . IsValidIndex ( EdgePolygonIDValue ) ) ;
const uint32 TestSmoothGroup = FaceSmoothingMasks [ EdgePolygonIDValue ] ;
if ( ( TestSmoothGroup & ReferenceSmoothGroup ) = = 0 )
{
EdgeHardnesses [ EdgeID ] = true ;
break ;
}
else
{
ConnectedPolygons . Add ( EdgePolygonID ) ;
}
}
}
ConsumedPolygons [ CurrentPolygonID . GetValue ( ) ] = true ;
}
}
}
void FStaticMeshOperations : : ConvertToRawMesh ( const FMeshDescription & SourceMeshDescription , FRawMesh & DestinationRawMesh , const TMap < FName , int32 > & MaterialMap )
{
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : ConvertToRawMesh ) ;
DestinationRawMesh . Empty ( ) ;
//Gather all array data
2020-07-16 08:23:15 -04:00
FStaticMeshConstAttributes Attributes ( SourceMeshDescription ) ;
2021-05-05 15:07:25 -04:00
TVertexAttributesConstRef < FVector3f > VertexPositions = Attributes . GetVertexPositions ( ) ;
TVertexInstanceAttributesConstRef < FVector3f > VertexInstanceNormals = Attributes . GetVertexInstanceNormals ( ) ;
TVertexInstanceAttributesConstRef < FVector3f > VertexInstanceTangents = Attributes . GetVertexInstanceTangents ( ) ;
2020-07-16 08:23:15 -04:00
TVertexInstanceAttributesConstRef < float > VertexInstanceBinormalSigns = Attributes . GetVertexInstanceBinormalSigns ( ) ;
2021-09-22 10:01:48 -04:00
TVertexInstanceAttributesConstRef < FVector4f > VertexInstanceColors = Attributes . GetVertexInstanceColors ( ) ;
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesConstRef < FVector2f > VertexInstanceUVs = Attributes . GetVertexInstanceUVs ( ) ;
2020-07-16 08:23:15 -04:00
TPolygonGroupAttributesConstRef < FName > PolygonGroupMaterialSlotName = Attributes . GetPolygonGroupMaterialSlotNames ( ) ;
2020-01-23 16:28:59 -05:00
DestinationRawMesh . VertexPositions . AddZeroed ( SourceMeshDescription . Vertices ( ) . Num ( ) ) ;
TArray < int32 > RemapVerts ;
RemapVerts . AddZeroed ( SourceMeshDescription . Vertices ( ) . GetArraySize ( ) ) ;
int32 VertexIndex = 0 ;
2022-01-06 16:44:09 +00:00
for ( const FVertexID VertexID : SourceMeshDescription . Vertices ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
DestinationRawMesh . VertexPositions [ VertexIndex ] = VertexPositions [ VertexID ] ;
RemapVerts [ VertexID . GetValue ( ) ] = VertexIndex ;
+ + VertexIndex ;
}
int32 TriangleNumber = SourceMeshDescription . Triangles ( ) . Num ( ) ;
DestinationRawMesh . FaceMaterialIndices . AddZeroed ( TriangleNumber ) ;
DestinationRawMesh . FaceSmoothingMasks . AddZeroed ( TriangleNumber ) ;
bool bHasVertexColor = HasVertexColor ( SourceMeshDescription ) ;
int32 WedgeIndexNumber = TriangleNumber * 3 ;
if ( bHasVertexColor )
{
DestinationRawMesh . WedgeColors . AddZeroed ( WedgeIndexNumber ) ;
}
DestinationRawMesh . WedgeIndices . AddZeroed ( WedgeIndexNumber ) ;
DestinationRawMesh . WedgeTangentX . AddZeroed ( WedgeIndexNumber ) ;
DestinationRawMesh . WedgeTangentY . AddZeroed ( WedgeIndexNumber ) ;
DestinationRawMesh . WedgeTangentZ . AddZeroed ( WedgeIndexNumber ) ;
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 ExistingUVCount = VertexInstanceUVs . GetNumChannels ( ) ;
2020-01-23 16:28:59 -05:00
for ( int32 UVIndex = 0 ; UVIndex < ExistingUVCount ; + + UVIndex )
{
DestinationRawMesh . WedgeTexCoords [ UVIndex ] . AddZeroed ( WedgeIndexNumber ) ;
}
int32 TriangleIndex = 0 ;
int32 WedgeIndex = 0 ;
for ( const FPolygonID PolygonID : SourceMeshDescription . Polygons ( ) . GetElementIDs ( ) )
{
const FPolygonGroupID & PolygonGroupID = SourceMeshDescription . GetPolygonPolygonGroup ( PolygonID ) ;
int32 PolygonIDValue = PolygonID . GetValue ( ) ;
2020-07-16 08:23:15 -04:00
TArrayView < const FTriangleID > TriangleIDs = SourceMeshDescription . GetPolygonTriangles ( PolygonID ) ;
2022-01-06 16:44:09 +00:00
for ( const FTriangleID & TriangleID : TriangleIDs )
2020-01-23 16:28:59 -05:00
{
if ( MaterialMap . Num ( ) > 0 & & MaterialMap . Contains ( PolygonGroupMaterialSlotName [ PolygonGroupID ] ) )
{
DestinationRawMesh . FaceMaterialIndices [ TriangleIndex ] = MaterialMap [ PolygonGroupMaterialSlotName [ PolygonGroupID ] ] ;
}
else
{
DestinationRawMesh . FaceMaterialIndices [ TriangleIndex ] = PolygonGroupID . GetValue ( ) ;
}
DestinationRawMesh . FaceSmoothingMasks [ TriangleIndex ] = 0 ; //Conversion of soft/hard to smooth mask is done after the geometry is converted
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
const FVertexInstanceID VertexInstanceID = SourceMeshDescription . GetTriangleVertexInstance ( TriangleID , Corner ) ;
if ( bHasVertexColor )
{
DestinationRawMesh . WedgeColors [ WedgeIndex ] = FLinearColor ( VertexInstanceColors [ VertexInstanceID ] ) . ToFColor ( true ) ;
}
DestinationRawMesh . WedgeIndices [ WedgeIndex ] = RemapVerts [ SourceMeshDescription . GetVertexInstanceVertex ( VertexInstanceID ) . GetValue ( ) ] ;
DestinationRawMesh . WedgeTangentX [ WedgeIndex ] = VertexInstanceTangents [ VertexInstanceID ] ;
2021-11-18 14:37:34 -05:00
DestinationRawMesh . WedgeTangentY [ WedgeIndex ] = FVector3f : : CrossProduct ( VertexInstanceNormals [ VertexInstanceID ] , VertexInstanceTangents [ VertexInstanceID ] ) . GetSafeNormal ( ) * VertexInstanceBinormalSigns [ VertexInstanceID ] ;
2020-01-23 16:28:59 -05:00
DestinationRawMesh . WedgeTangentZ [ WedgeIndex ] = VertexInstanceNormals [ VertexInstanceID ] ;
for ( int32 UVIndex = 0 ; UVIndex < ExistingUVCount ; + + UVIndex )
{
DestinationRawMesh . WedgeTexCoords [ UVIndex ] [ WedgeIndex ] = VertexInstanceUVs . Get ( VertexInstanceID , UVIndex ) ;
}
+ + WedgeIndex ;
}
+ + TriangleIndex ;
}
}
//Convert the smoothgroup
ConvertHardEdgesToSmoothGroup ( SourceMeshDescription , DestinationRawMesh . FaceSmoothingMasks ) ;
}
//We want to fill the FMeshDescription vertex position mesh attribute with the FRawMesh vertex position
//We will also weld the vertex position (old FRawMesh is not always welded) and construct a mapping array to match the FVertexID
2021-05-05 15:07:25 -04:00
void FillMeshDescriptionVertexPositionNoDuplicate ( const TArray < FVector3f > & RawMeshVertexPositions , FMeshDescription & DestinationMeshDescription , TArray < FVertexID > & RemapVertexPosition )
2020-01-23 16:28:59 -05:00
{
2021-05-05 15:07:25 -04:00
TVertexAttributesRef < FVector3f > VertexPositions = DestinationMeshDescription . GetVertexPositions ( ) ;
2020-01-23 16:28:59 -05:00
const int32 NumVertex = RawMeshVertexPositions . Num ( ) ;
TMap < int32 , int32 > TempRemapVertexPosition ;
TempRemapVertexPosition . Reserve ( NumVertex ) ;
// Create a list of vertex Z/index pairs
TArray < MeshDescriptionOperationNamespace : : FIndexAndZ > VertIndexAndZ ;
VertIndexAndZ . Reserve ( NumVertex ) ;
for ( int32 VertexIndex = 0 ; VertexIndex < NumVertex ; + + VertexIndex )
{
2023-05-09 05:17:49 -04:00
VertIndexAndZ . Emplace ( VertexIndex , RawMeshVertexPositions [ VertexIndex ] ) ;
2020-01-23 16:28:59 -05:00
}
// Sort the vertices by z value
VertIndexAndZ . Sort ( MeshDescriptionOperationNamespace : : FCompareIndexAndZ ( ) ) ;
int32 VertexCount = 0 ;
// Search for duplicates, quickly!
for ( int32 i = 0 ; i < VertIndexAndZ . Num ( ) ; i + + )
{
int32 Index_i = VertIndexAndZ [ i ] . Index ;
if ( TempRemapVertexPosition . Contains ( Index_i ) )
{
continue ;
}
TempRemapVertexPosition . FindOrAdd ( Index_i ) = VertexCount ;
// only need to search forward, since we add pairs both ways
for ( int32 j = i + 1 ; j < VertIndexAndZ . Num ( ) ; j + + )
{
if ( FMath : : Abs ( VertIndexAndZ [ j ] . Z - VertIndexAndZ [ i ] . Z ) > SMALL_NUMBER )
break ; // can't be any more dups
2021-11-18 14:37:34 -05:00
const FVector3f & PositionA = * ( VertIndexAndZ [ i ] . OriginalVector ) ;
const FVector3f & PositionB = * ( VertIndexAndZ [ j ] . OriginalVector ) ;
2020-01-23 16:28:59 -05:00
if ( PositionA . Equals ( PositionB , SMALL_NUMBER ) )
{
TempRemapVertexPosition . FindOrAdd ( VertIndexAndZ [ j ] . Index ) = VertexCount ;
}
}
VertexCount + + ;
}
//Make sure the vertex are added in the same order to be lossless when converting the FRawMesh
//In case there is a duplicate even reordering it will not be lossless, but MeshDescription do not support
//bad data like duplicated vertex position.
RemapVertexPosition . AddUninitialized ( NumVertex ) ;
DestinationMeshDescription . ReserveNewVertices ( VertexCount ) ;
TArray < FVertexID > UniqueVertexDone ;
UniqueVertexDone . AddUninitialized ( VertexCount ) ;
for ( int32 VertexIndex = 0 ; VertexIndex < VertexCount ; + + VertexIndex )
{
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
UniqueVertexDone [ VertexIndex ] = INDEX_NONE ;
2020-01-23 16:28:59 -05:00
}
for ( int32 VertexIndex = 0 ; VertexIndex < NumVertex ; + + VertexIndex )
{
int32 RealIndex = TempRemapVertexPosition [ VertexIndex ] ;
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
if ( UniqueVertexDone [ RealIndex ] ! = INDEX_NONE )
2020-01-23 16:28:59 -05:00
{
RemapVertexPosition [ VertexIndex ] = UniqueVertexDone [ RealIndex ] ;
continue ;
}
FVertexID VertexID = DestinationMeshDescription . CreateVertex ( ) ;
UniqueVertexDone [ RealIndex ] = VertexID ;
VertexPositions [ VertexID ] = RawMeshVertexPositions [ VertexIndex ] ;
RemapVertexPosition [ VertexIndex ] = VertexID ;
}
}
//Discover degenerated triangle
bool IsTriangleDegenerated ( const FRawMesh & SourceRawMesh , const TArray < FVertexID > & RemapVertexPosition , const int32 VerticeIndexBase )
{
FVertexID VertexIDs [ 3 ] ;
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
int32 VerticeIndex = VerticeIndexBase + Corner ;
VertexIDs [ Corner ] = RemapVertexPosition [ SourceRawMesh . WedgeIndices [ VerticeIndex ] ] ;
}
return ( VertexIDs [ 0 ] = = VertexIDs [ 1 ] | | VertexIDs [ 0 ] = = VertexIDs [ 2 ] | | VertexIDs [ 1 ] = = VertexIDs [ 2 ] ) ;
}
2023-02-11 12:51:08 -05:00
void FStaticMeshOperations : : ConvertFromRawMesh ( const FRawMesh & SourceRawMesh , FMeshDescription & DestinationMeshDescription , const TMap < int32 , FName > & MaterialMap , bool bSkipNormalsAndTangents , const TCHAR * DebugName )
2020-01-23 16:28:59 -05:00
{
DestinationMeshDescription . Empty ( ) ;
DestinationMeshDescription . ReserveNewVertexInstances ( SourceRawMesh . WedgeIndices . Num ( ) ) ;
DestinationMeshDescription . ReserveNewPolygons ( SourceRawMesh . WedgeIndices . Num ( ) / 3 ) ;
//Approximately 2.5 edges per polygons
DestinationMeshDescription . ReserveNewEdges ( SourceRawMesh . WedgeIndices . Num ( ) * 2.5f / 3 ) ;
//Gather all array data
2021-05-05 15:07:25 -04:00
TVertexInstanceAttributesRef < FVector3f > VertexInstanceNormals = DestinationMeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector3f > ( MeshAttribute : : VertexInstance : : Normal ) ;
TVertexInstanceAttributesRef < FVector3f > VertexInstanceTangents = DestinationMeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector3f > ( MeshAttribute : : VertexInstance : : Tangent ) ;
2020-01-23 16:28:59 -05:00
TVertexInstanceAttributesRef < float > VertexInstanceBinormalSigns = DestinationMeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < float > ( MeshAttribute : : VertexInstance : : BinormalSign ) ;
2021-09-22 10:01:48 -04:00
TVertexInstanceAttributesRef < FVector4f > VertexInstanceColors = DestinationMeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector4f > ( MeshAttribute : : VertexInstance : : Color ) ;
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesRef < FVector2f > VertexInstanceUVs = DestinationMeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector2f > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
2020-01-23 16:28:59 -05:00
TPolygonGroupAttributesRef < FName > PolygonGroupImportedMaterialSlotNames = DestinationMeshDescription . PolygonGroupAttributes ( ) . GetAttributesRef < FName > ( MeshAttribute : : PolygonGroup : : ImportedMaterialSlotName ) ;
int32 NumTexCoords = 0 ;
int32 MaxTexCoords = MAX_MESH_TEXTURE_COORDS ;
TArray < int32 > TextureCoordinnateRemapIndex ;
TextureCoordinnateRemapIndex . AddZeroed ( MaxTexCoords ) ;
for ( int32 TextureCoordinnateIndex = 0 ; TextureCoordinnateIndex < MaxTexCoords ; + + TextureCoordinnateIndex )
{
TextureCoordinnateRemapIndex [ TextureCoordinnateIndex ] = INDEX_NONE ;
if ( SourceRawMesh . WedgeTexCoords [ TextureCoordinnateIndex ] . Num ( ) = = SourceRawMesh . WedgeIndices . Num ( ) )
{
TextureCoordinnateRemapIndex [ TextureCoordinnateIndex ] = NumTexCoords ;
NumTexCoords + + ;
}
}
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 ( NumTexCoords ) ;
2020-01-23 16:28:59 -05:00
//Ensure we do not have any duplicate, We found all duplicated vertex and compact them and build a remap indice array to remap the wedgeindices
TArray < FVertexID > RemapVertexPosition ;
FillMeshDescriptionVertexPositionNoDuplicate ( SourceRawMesh . VertexPositions , DestinationMeshDescription , RemapVertexPosition ) ;
bool bHasColors = SourceRawMesh . WedgeColors . Num ( ) > 0 ;
bool bHasTangents = SourceRawMesh . WedgeTangentX . Num ( ) > 0 & & SourceRawMesh . WedgeTangentY . Num ( ) > 0 ;
bool bHasNormals = SourceRawMesh . WedgeTangentZ . Num ( ) > 0 ;
TArray < FPolygonGroupID > PolygonGroups ;
TMap < int32 , FPolygonGroupID > MaterialIndexToPolygonGroup ;
//Create the PolygonGroups
for ( int32 MaterialIndex : SourceRawMesh . FaceMaterialIndices )
{
if ( ! MaterialIndexToPolygonGroup . Contains ( MaterialIndex ) )
{
FPolygonGroupID PolygonGroupID ( MaterialIndex ) ;
DestinationMeshDescription . CreatePolygonGroupWithID ( PolygonGroupID ) ;
if ( MaterialMap . Contains ( MaterialIndex ) )
{
PolygonGroupImportedMaterialSlotNames [ PolygonGroupID ] = MaterialMap [ MaterialIndex ] ;
}
else
{
PolygonGroupImportedMaterialSlotNames [ PolygonGroupID ] = FName ( * FString : : Printf ( TEXT ( " MaterialSlot_%d " ) , MaterialIndex ) ) ;
}
PolygonGroups . Add ( PolygonGroupID ) ;
MaterialIndexToPolygonGroup . Add ( MaterialIndex , PolygonGroupID ) ;
}
}
//Triangles
int32 TriangleCount = SourceRawMesh . WedgeIndices . Num ( ) / 3 ;
2020-09-24 00:43:27 -04:00
// Reserve enough memory to avoid as much as possible reallocations
DestinationMeshDescription . ReserveNewVertexInstances ( SourceRawMesh . WedgeIndices . Num ( ) ) ;
DestinationMeshDescription . ReserveNewTriangles ( TriangleCount ) ;
DestinationMeshDescription . ReserveNewPolygons ( TriangleCount ) ;
DestinationMeshDescription . ReserveNewEdges ( TriangleCount * 2 ) ;
2020-01-23 16:28:59 -05:00
for ( int32 TriangleIndex = 0 ; TriangleIndex < TriangleCount ; + + TriangleIndex )
{
int32 VerticeIndexBase = TriangleIndex * 3 ;
//Check if the triangle is degenerated and skip the data if its the case
if ( IsTriangleDegenerated ( SourceRawMesh , RemapVertexPosition , VerticeIndexBase ) )
{
continue ;
}
//PolygonGroup
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
FPolygonGroupID PolygonGroupID = INDEX_NONE ;
2020-01-23 16:28:59 -05:00
FName PolygonGroupImportedMaterialSlotName = NAME_None ;
int32 MaterialIndex = SourceRawMesh . FaceMaterialIndices [ TriangleIndex ] ;
if ( MaterialIndexToPolygonGroup . Contains ( MaterialIndex ) )
{
PolygonGroupID = MaterialIndexToPolygonGroup [ MaterialIndex ] ;
}
else if ( MaterialMap . Num ( ) > 0 & & MaterialMap . Contains ( MaterialIndex ) )
{
PolygonGroupImportedMaterialSlotName = MaterialMap [ MaterialIndex ] ;
2022-01-06 16:44:09 +00:00
for ( const FPolygonGroupID SearchPolygonGroupID : DestinationMeshDescription . PolygonGroups ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
if ( PolygonGroupImportedMaterialSlotNames [ SearchPolygonGroupID ] = = PolygonGroupImportedMaterialSlotName )
{
PolygonGroupID = SearchPolygonGroupID ;
break ;
}
}
}
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
if ( PolygonGroupID = = INDEX_NONE )
2020-01-23 16:28:59 -05:00
{
PolygonGroupID = DestinationMeshDescription . CreatePolygonGroup ( ) ;
2021-04-28 01:58:36 -04:00
PolygonGroupImportedMaterialSlotNames [ PolygonGroupID ] = ( PolygonGroupImportedMaterialSlotName = = NAME_None ) ? FName ( * FString : : Printf ( TEXT ( " MaterialSlot_%d " ) , MaterialIndex ) ) : PolygonGroupImportedMaterialSlotName ;
2020-01-23 16:28:59 -05:00
PolygonGroups . Add ( PolygonGroupID ) ;
MaterialIndexToPolygonGroup . Add ( MaterialIndex , PolygonGroupID ) ;
}
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
FVertexInstanceID TriangleVertexInstanceIDs [ 3 ] ;
2020-01-23 16:28:59 -05:00
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
int32 VerticeIndex = VerticeIndexBase + Corner ;
FVertexID VertexID = RemapVertexPosition [ SourceRawMesh . WedgeIndices [ VerticeIndex ] ] ;
FVertexInstanceID VertexInstanceID = DestinationMeshDescription . CreateVertexInstance ( VertexID ) ;
TriangleVertexInstanceIDs [ Corner ] = VertexInstanceID ;
2022-01-27 03:30:41 -05:00
VertexInstanceColors [ VertexInstanceID ] = bHasColors ? FVector4f ( FLinearColor : : FromSRGBColor ( SourceRawMesh . WedgeColors [ VerticeIndex ] ) ) : FVector4f ( FLinearColor : : White ) ;
2021-05-05 15:07:25 -04:00
VertexInstanceNormals [ VertexInstanceID ] = bHasNormals ? SourceRawMesh . WedgeTangentZ [ VerticeIndex ] : FVector3f ( ForceInitToZero ) ;
2020-01-23 16:28:59 -05:00
if ( bHasTangents )
{
VertexInstanceTangents [ VertexInstanceID ] = SourceRawMesh . WedgeTangentX [ VerticeIndex ] ;
2021-11-18 14:37:34 -05:00
VertexInstanceBinormalSigns [ VertexInstanceID ] = FMatrix44f ( SourceRawMesh . WedgeTangentX [ VerticeIndex ] . GetSafeNormal ( ) ,
2020-01-23 16:28:59 -05:00
SourceRawMesh . WedgeTangentY [ VerticeIndex ] . GetSafeNormal ( ) ,
SourceRawMesh . WedgeTangentZ [ VerticeIndex ] . GetSafeNormal ( ) ,
2021-11-18 14:37:34 -05:00
FVector3f : : ZeroVector ) . Determinant ( ) < 0 ? - 1.0f : + 1.0f ;
2020-01-23 16:28:59 -05:00
}
else
{
2021-11-18 14:37:34 -05:00
VertexInstanceTangents [ VertexInstanceID ] = FVector3f ( ForceInitToZero ) ;
2020-01-23 16:28:59 -05:00
VertexInstanceBinormalSigns [ VertexInstanceID ] = 0.0f ;
}
for ( int32 TextureCoordinnateIndex = 0 ; TextureCoordinnateIndex < NumTexCoords ; + + TextureCoordinnateIndex )
{
int32 TextureCoordIndex = TextureCoordinnateRemapIndex [ TextureCoordinnateIndex ] ;
if ( TextureCoordIndex = = INDEX_NONE )
{
continue ;
}
VertexInstanceUVs . Set ( VertexInstanceID , TextureCoordIndex , SourceRawMesh . WedgeTexCoords [ TextureCoordinnateIndex ] [ VerticeIndex ] ) ;
}
}
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
DestinationMeshDescription . CreateTriangle ( PolygonGroupID , TriangleVertexInstanceIDs ) ;
2020-01-23 16:28:59 -05:00
}
ConvertSmoothGroupToHardEdges ( SourceRawMesh . FaceSmoothingMasks , DestinationMeshDescription ) ;
//Create the missing normals and tangents, should we use Mikkt space for tangent???
2020-02-19 06:00:18 -05:00
if ( ! bSkipNormalsAndTangents & & ( ! bHasNormals | | ! bHasTangents ) )
2020-01-23 16:28:59 -05:00
{
//DestinationMeshDescription.ComputePolygonTangentsAndNormals(0.0f);
2023-02-11 12:51:08 -05:00
ComputeTriangleTangentsAndNormals ( DestinationMeshDescription , 0.0f , DebugName ) ;
2020-01-23 16:28:59 -05:00
//Create the missing normals and recompute the tangents with MikkTSpace.
EComputeNTBsFlags ComputeNTBsOptions = EComputeNTBsFlags : : Tangents | EComputeNTBsFlags : : UseMikkTSpace | EComputeNTBsFlags : : BlendOverlappingNormals ;
ComputeTangentsAndNormals ( DestinationMeshDescription , ComputeNTBsOptions ) ;
}
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
DestinationMeshDescription . BuildIndexers ( ) ;
2020-01-23 16:28:59 -05:00
}
2021-02-16 13:49:10 -04:00
void FStaticMeshOperations : : AppendMeshDescriptions ( const TArray < const FMeshDescription * > & SourceMeshes , FMeshDescription & TargetMesh , FAppendSettings & AppendSettings )
2020-01-23 16:28:59 -05:00
{
2021-02-16 13:49:10 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE_STR ( ( SourceMeshes . Num ( ) > 1 ? " FStaticMeshOperations::AppendMeshDescriptions " : " FStaticMeshOperations::AppendMeshDescription " ) ) ;
2020-01-23 16:28:59 -05:00
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
FStaticMeshAttributes TargetAttributes ( TargetMesh ) ;
2021-05-05 15:07:25 -04:00
TVertexAttributesRef < FVector3f > TargetVertexPositions = TargetAttributes . GetVertexPositions ( ) ;
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
TEdgeAttributesRef < bool > TargetEdgeHardnesses = TargetAttributes . GetEdgeHardnesses ( ) ;
TPolygonGroupAttributesRef < FName > TargetImportedMaterialSlotNames = TargetAttributes . GetPolygonGroupMaterialSlotNames ( ) ;
2021-05-05 15:07:25 -04:00
TVertexInstanceAttributesRef < FVector3f > TargetVertexInstanceNormals = TargetAttributes . GetVertexInstanceNormals ( ) ;
TVertexInstanceAttributesRef < FVector3f > TargetVertexInstanceTangents = TargetAttributes . GetVertexInstanceTangents ( ) ;
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
TVertexInstanceAttributesRef < float > TargetVertexInstanceBinormalSigns = TargetAttributes . GetVertexInstanceBinormalSigns ( ) ;
2021-09-22 10:01:48 -04:00
TVertexInstanceAttributesRef < FVector4f > TargetVertexInstanceColors = TargetAttributes . GetVertexInstanceColors ( ) ;
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesRef < FVector2f > TargetVertexInstanceUVs = TargetAttributes . GetVertexInstanceUVs ( ) ;
2020-01-23 16:28:59 -05:00
2021-02-16 13:49:10 -04:00
TargetMesh . SuspendVertexInstanceIndexing ( ) ;
TargetMesh . SuspendEdgeIndexing ( ) ;
TargetMesh . SuspendPolygonIndexing ( ) ;
TargetMesh . SuspendPolygonGroupIndexing ( ) ;
TargetMesh . SuspendUVIndexing ( ) ;
int32 NumVertices = 0 ;
int32 NumVertexInstances = 0 ;
int32 NumEdges = 0 ;
int32 NumTriangles = 0 ;
2023-02-28 12:13:16 -05:00
int32 MaxNumVertexInstanceUVChannels = TargetVertexInstanceUVs . GetNumChannels ( ) ;
int32 MaxNumUVChannels = TargetMesh . GetNumUVElementChannels ( ) ;
2021-02-16 13:49:10 -04:00
int32 MaxNumPolygonGroups = 0 ;
int32 MaxNumMeshVertices = 0 ;
int32 MaxNumEdges = 0 ;
int32 MaxNumVertexInstances = 0 ;
for ( const FMeshDescription * SourceMeshPtr : SourceMeshes )
{
const FMeshDescription & SourceMesh = * SourceMeshPtr ;
NumVertices + = SourceMesh . Vertices ( ) . Num ( ) ;
NumVertexInstances + = SourceMesh . VertexInstances ( ) . Num ( ) ;
NumEdges + = SourceMesh . Edges ( ) . Num ( ) ;
NumTriangles + = SourceMesh . Triangles ( ) . Num ( ) ;
FStaticMeshConstAttributes SourceAttributes ( SourceMesh ) ;
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesConstRef < FVector2f > SourceVertexInstanceUVs = SourceAttributes . GetVertexInstanceUVs ( ) ;
2023-02-28 12:13:16 -05:00
for ( int32 ChannelIdx = MaxNumVertexInstanceUVChannels ; ChannelIdx < SourceVertexInstanceUVs . GetNumChannels ( ) ; + + ChannelIdx )
{
if ( AppendSettings . bMergeUVChannels [ ChannelIdx ] )
{
MaxNumVertexInstanceUVChannels = ChannelIdx + 1 ;
}
}
for ( int32 ChannelIdx = MaxNumUVChannels ; ChannelIdx < SourceMesh . GetNumUVElementChannels ( ) ; + + ChannelIdx )
2021-02-16 13:49:10 -04:00
{
if ( AppendSettings . bMergeUVChannels [ ChannelIdx ] )
{
MaxNumUVChannels = ChannelIdx + 1 ;
}
}
MaxNumPolygonGroups = FMath : : Max ( MaxNumPolygonGroups , SourceMesh . PolygonGroups ( ) . Num ( ) ) ;
MaxNumMeshVertices = FMath : : Max ( MaxNumMeshVertices , SourceMesh . Vertices ( ) . Num ( ) ) ;
MaxNumEdges = FMath : : Max ( MaxNumEdges , SourceMesh . Edges ( ) . Num ( ) ) ;
MaxNumVertexInstances = FMath : : Max ( MaxNumVertexInstances , SourceMesh . VertexInstances ( ) . Num ( ) ) ;
}
2020-01-23 16:28:59 -05:00
//Copy into the target mesh
2021-02-16 13:49:10 -04:00
TargetMesh . ReserveNewVertices ( NumVertices ) ;
TargetMesh . ReserveNewVertexInstances ( NumVertexInstances ) ;
TargetMesh . ReserveNewEdges ( NumEdges ) ;
TargetMesh . ReserveNewTriangles ( NumTriangles ) ;
2020-01-23 16:28:59 -05:00
2023-02-28 12:13:16 -05:00
if ( MaxNumVertexInstanceUVChannels > TargetVertexInstanceUVs . GetNumChannels ( ) )
2020-01-23 16:28:59 -05:00
{
2023-02-28 12:13:16 -05:00
TargetVertexInstanceUVs . SetNumChannels ( MaxNumVertexInstanceUVChannels ) ;
}
if ( MaxNumUVChannels > TargetMesh . GetNumUVElementChannels ( ) )
{
TargetMesh . SetNumUVChannels ( MaxNumUVChannels ) ;
2020-03-05 16:01:44 -05:00
}
2020-01-23 16:28:59 -05:00
PolygonGroupMap RemapPolygonGroup ;
2021-02-16 13:49:10 -04:00
TMap < FVertexID , FVertexID > SourceToTargetVertexID ;
SourceToTargetVertexID . Reserve ( MaxNumMeshVertices ) ;
TMap < FVertexInstanceID , FVertexInstanceID > SourceToTargetVertexInstanceID ;
SourceToTargetVertexInstanceID . Reserve ( MaxNumVertexInstances ) ;
for ( const FMeshDescription * SourceMeshPtr : SourceMeshes )
2020-01-23 16:28:59 -05:00
{
2021-02-16 13:49:10 -04:00
const FMeshDescription & SourceMesh = * SourceMeshPtr ;
RemapPolygonGroup . Empty ( MaxNumPolygonGroups ) ;
FStaticMeshConstAttributes SourceAttributes ( SourceMesh ) ;
2021-05-05 15:07:25 -04:00
TVertexAttributesConstRef < FVector3f > SourceVertexPositions = SourceAttributes . GetVertexPositions ( ) ;
2021-02-16 13:49:10 -04:00
TEdgeAttributesConstRef < bool > SourceEdgeHardnesses = SourceAttributes . GetEdgeHardnesses ( ) ;
TPolygonGroupAttributesConstRef < FName > SourceImportedMaterialSlotNames = SourceAttributes . GetPolygonGroupMaterialSlotNames ( ) ;
2021-05-05 15:07:25 -04:00
TVertexInstanceAttributesConstRef < FVector3f > SourceVertexInstanceNormals = SourceAttributes . GetVertexInstanceNormals ( ) ;
TVertexInstanceAttributesConstRef < FVector3f > SourceVertexInstanceTangents = SourceAttributes . GetVertexInstanceTangents ( ) ;
2021-02-16 13:49:10 -04:00
TVertexInstanceAttributesConstRef < float > SourceVertexInstanceBinormalSigns = SourceAttributes . GetVertexInstanceBinormalSigns ( ) ;
2021-09-22 10:01:48 -04:00
TVertexInstanceAttributesConstRef < FVector4f > SourceVertexInstanceColors = SourceAttributes . GetVertexInstanceColors ( ) ;
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesConstRef < FVector2f > SourceVertexInstanceUVs = SourceAttributes . GetVertexInstanceUVs ( ) ;
2021-02-16 13:49:10 -04:00
2023-02-28 12:13:16 -05:00
// Fill the UV arrays
const int32 NumUVChannel = FMath : : Min ( TargetMesh . GetNumUVElementChannels ( ) , SourceMesh . GetNumUVElementChannels ( ) ) ;
for ( int32 UVLayerIndex = 0 ; UVLayerIndex < NumUVChannel ; UVLayerIndex + + )
{
TUVAttributesConstRef < FVector2f > SourceUVCoordinates = SourceMesh . UVAttributes ( UVLayerIndex ) . GetAttributesRef < FVector2f > ( MeshAttribute : : UV : : UVCoordinate ) ;
TUVAttributesRef < FVector2f > TargetUVCoordinates = TargetMesh . UVAttributes ( UVLayerIndex ) . GetAttributesRef < FVector2f > ( MeshAttribute : : UV : : UVCoordinate ) ;
int32 UVCount = SourceUVCoordinates . GetNumElements ( ) ;
TargetMesh . ReserveNewUVs ( UVCount , UVLayerIndex ) ;
for ( FUVID SourceUVID : SourceMesh . UVs ( UVLayerIndex ) . GetElementIDs ( ) )
{
FUVID TargetUVID = TargetMesh . CreateUV ( UVLayerIndex ) ;
TargetUVCoordinates [ TargetUVID ] = SourceUVCoordinates [ SourceUVID ] ;
}
}
2021-02-16 13:49:10 -04:00
//PolygonGroups
if ( AppendSettings . PolygonGroupsDelegate . IsBound ( ) )
2020-01-23 16:28:59 -05:00
{
2021-02-16 13:49:10 -04:00
AppendSettings . PolygonGroupsDelegate . Execute ( SourceMesh , TargetMesh , RemapPolygonGroup ) ;
}
else
{
for ( FPolygonGroupID SourcePolygonGroupID : SourceMesh . PolygonGroups ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
2021-02-16 13:49:10 -04:00
FPolygonGroupID TargetMatchingID = INDEX_NONE ;
for ( FPolygonGroupID TargetPolygonGroupID : TargetMesh . PolygonGroups ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
2021-02-16 13:49:10 -04:00
if ( SourceImportedMaterialSlotNames [ SourcePolygonGroupID ] = = TargetImportedMaterialSlotNames [ TargetPolygonGroupID ] )
{
TargetMatchingID = TargetPolygonGroupID ;
break ;
}
2020-01-23 16:28:59 -05:00
}
2021-02-16 13:49:10 -04:00
if ( TargetMatchingID = = INDEX_NONE )
{
TargetMatchingID = TargetMesh . CreatePolygonGroup ( ) ;
TargetImportedMaterialSlotNames [ TargetMatchingID ] = SourceImportedMaterialSlotNames [ SourcePolygonGroupID ] ;
}
RemapPolygonGroup . Add ( SourcePolygonGroupID , TargetMatchingID ) ;
2020-01-23 16:28:59 -05:00
}
2021-02-16 13:49:10 -04:00
}
FPolygonGroupID SinglePolygonGroup = TargetMesh . PolygonGroups ( ) . Num ( ) = = 1 ? TargetMesh . PolygonGroups ( ) . GetFirstValidID ( ) : INDEX_NONE ;
//Vertices
for ( FVertexID SourceVertexID : SourceMesh . Vertices ( ) . GetElementIDs ( ) )
{
FVertexID TargetVertexID = TargetMesh . CreateVertex ( ) ;
2022-02-02 07:59:31 -05:00
TargetVertexPositions [ TargetVertexID ] = ( SourceVertexPositions [ SourceVertexID ] - FVector3f ( AppendSettings . MergedAssetPivot ) ) ; //LWC_TODO: Precision loss
2021-02-16 13:49:10 -04:00
SourceToTargetVertexID . Add ( SourceVertexID , TargetVertexID ) ;
}
// Transform vertices properties
if ( AppendSettings . MeshTransform )
{
const FTransform & Transform = AppendSettings . MeshTransform . GetValue ( ) ;
for ( const TPair < FVertexID , FVertexID > & VertexIDPair : SourceToTargetVertexID )
2020-01-23 16:28:59 -05:00
{
2021-05-05 15:07:25 -04:00
FVector3f & Position = TargetVertexPositions [ VertexIDPair . Value ] ;
2022-02-02 07:59:31 -05:00
Position = FVector3f ( Transform . TransformPosition ( FVector ( Position ) ) ) ; //LWC_TODO: Precision loss
2020-01-23 16:28:59 -05:00
}
}
2021-02-16 13:49:10 -04:00
//Edges
for ( const FEdgeID SourceEdgeID : SourceMesh . Edges ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
2021-02-16 13:49:10 -04:00
const FVertexID EdgeVertex0 = SourceMesh . GetEdgeVertex ( SourceEdgeID , 0 ) ;
const FVertexID EdgeVertex1 = SourceMesh . GetEdgeVertex ( SourceEdgeID , 1 ) ;
FEdgeID TargetEdgeID = TargetMesh . CreateEdge ( SourceToTargetVertexID [ EdgeVertex0 ] , SourceToTargetVertexID [ EdgeVertex1 ] ) ;
TargetEdgeHardnesses [ TargetEdgeID ] = SourceEdgeHardnesses [ SourceEdgeID ] ;
2020-01-23 16:28:59 -05:00
}
2021-02-16 13:49:10 -04:00
//VertexInstances
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID SourceVertexInstanceID : SourceMesh . VertexInstances ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
2021-02-16 13:49:10 -04:00
const FVertexID SourceVertexID = SourceMesh . GetVertexInstanceVertex ( SourceVertexInstanceID ) ;
FVertexInstanceID TargetVertexInstanceID = TargetMesh . CreateVertexInstance ( SourceToTargetVertexID [ SourceVertexID ] ) ;
TargetVertexInstanceNormals [ TargetVertexInstanceID ] = SourceVertexInstanceNormals [ SourceVertexInstanceID ] ;
TargetVertexInstanceTangents [ TargetVertexInstanceID ] = SourceVertexInstanceTangents [ SourceVertexInstanceID ] ;
TargetVertexInstanceBinormalSigns [ TargetVertexInstanceID ] = SourceVertexInstanceBinormalSigns [ SourceVertexInstanceID ] ;
if ( AppendSettings . bMergeVertexColor )
{
TargetVertexInstanceColors [ TargetVertexInstanceID ] = SourceVertexInstanceColors [ SourceVertexInstanceID ] ;
}
2023-02-28 12:13:16 -05:00
for ( int32 UVChannelIndex = 0 ; UVChannelIndex < MaxNumVertexInstanceUVChannels & & UVChannelIndex < SourceVertexInstanceUVs . GetNumChannels ( ) ; + + UVChannelIndex )
2021-02-16 13:49:10 -04:00
{
TargetVertexInstanceUVs . Set ( TargetVertexInstanceID , UVChannelIndex , SourceVertexInstanceUVs . Get ( SourceVertexInstanceID , UVChannelIndex ) ) ;
}
SourceToTargetVertexInstanceID . Add ( SourceVertexInstanceID , TargetVertexInstanceID ) ;
2020-01-23 16:28:59 -05:00
}
2023-06-01 10:46:45 -04:00
bool bReverseCulling = false ;
2021-02-16 13:49:10 -04:00
// Transform vertex instances properties
if ( AppendSettings . MeshTransform )
2020-01-23 16:28:59 -05:00
{
2021-02-16 13:49:10 -04:00
const FTransform & Transform = AppendSettings . MeshTransform . GetValue ( ) ;
2023-08-16 17:03:55 -04:00
FMatrix TransformInverseTransposeMatrix = Transform . ToMatrixWithScale ( ) . Inverse ( ) . GetTransposed ( ) ;
TransformInverseTransposeMatrix . RemoveScaling ( ) ;
2023-06-01 10:46:45 -04:00
bReverseCulling = Transform . GetDeterminant ( ) < 0 ;
float BinormalSignsFactor = bReverseCulling ? - 1.f : 1.f ;
2021-02-16 13:49:10 -04:00
for ( const TPair < FVertexInstanceID , FVertexInstanceID > & VertexInstanceIDPair : SourceToTargetVertexInstanceID )
{
FVertexInstanceID InstanceID = VertexInstanceIDPair . Value ;
2021-05-05 15:07:25 -04:00
FVector3f & Normal = TargetVertexInstanceNormals [ InstanceID ] ;
2023-06-01 10:46:45 -04:00
Normal = ( FVector3f ) FVector ( TransformInverseTransposeMatrix . TransformVector ( ( FVector ) Normal ) . GetSafeNormal ( ) ) ;
2021-02-16 13:49:10 -04:00
2021-05-05 15:07:25 -04:00
FVector3f & Tangent = TargetVertexInstanceTangents [ InstanceID ] ;
2023-06-01 10:46:45 -04:00
Tangent = ( FVector3f ) FVector ( TransformInverseTransposeMatrix . TransformVector ( ( FVector ) Tangent ) . GetSafeNormal ( ) ) ;
2021-02-16 13:49:10 -04:00
TargetVertexInstanceBinormalSigns [ InstanceID ] * = BinormalSignsFactor ;
}
}
// Triangles
for ( const FTriangleID SourceTriangleID : SourceMesh . Triangles ( ) . GetElementIDs ( ) )
{
TArrayView < const FVertexInstanceID > TriangleVertexInstanceIDs = SourceMesh . GetTriangleVertexInstances ( SourceTriangleID ) ;
//Find the polygonGroupID
FPolygonGroupID TargetPolygonGroupID = SinglePolygonGroup ! = INDEX_NONE ? SinglePolygonGroup : RemapPolygonGroup [ SourceMesh . GetTrianglePolygonGroup ( SourceTriangleID ) ] ;
TArray < FVertexInstanceID , TInlineAllocator < 3 > > VertexInstanceIDs ;
VertexInstanceIDs . Reserve ( 3 ) ;
2023-06-01 10:46:45 -04:00
if ( bReverseCulling )
2021-02-16 13:49:10 -04:00
{
2023-06-01 10:46:45 -04:00
for ( int32 ReverseVertexInstanceIdIndex = TriangleVertexInstanceIDs . Num ( ) - 1 ; ReverseVertexInstanceIdIndex > = 0 ; ReverseVertexInstanceIdIndex - - )
{
VertexInstanceIDs . Add ( SourceToTargetVertexInstanceID [ TriangleVertexInstanceIDs [ ReverseVertexInstanceIdIndex ] ] ) ;
}
2021-02-16 13:49:10 -04:00
}
2023-06-01 10:46:45 -04:00
else
{
for ( const FVertexInstanceID & VertexInstanceID : TriangleVertexInstanceIDs )
{
VertexInstanceIDs . Add ( SourceToTargetVertexInstanceID [ VertexInstanceID ] ) ;
}
}
2021-02-16 13:49:10 -04:00
// Insert a triangle into the mesh
TargetMesh . CreateTriangle ( TargetPolygonGroupID , VertexInstanceIDs ) ;
2020-01-23 16:28:59 -05:00
}
}
2021-02-16 13:49:10 -04:00
TargetMesh . ResumeVertexInstanceIndexing ( ) ;
TargetMesh . ResumeEdgeIndexing ( ) ;
TargetMesh . ResumePolygonIndexing ( ) ;
TargetMesh . ResumePolygonGroupIndexing ( ) ;
TargetMesh . ResumeUVIndexing ( ) ;
2020-01-23 16:28:59 -05:00
}
2021-02-16 13:49:10 -04:00
void FStaticMeshOperations : : AppendMeshDescription ( const FMeshDescription & SourceMesh , FMeshDescription & TargetMesh , FAppendSettings & AppendSettings )
{
AppendMeshDescriptions ( { & SourceMesh } , TargetMesh , AppendSettings ) ;
}
2020-01-23 16:28:59 -05:00
//////////////////////////////////////////////////////////////////////////
// Normals tangents and Bi-normals
2024-04-30 22:25:26 -04:00
void FStaticMeshOperations : : HasInvalidVertexInstanceNormalsOrTangents ( const FMeshDescription & MeshDescription , bool & bHasInvalidNormals , bool & bHasInvalidTangents )
2020-01-23 16:28:59 -05:00
{
bHasInvalidNormals = false ;
bHasInvalidTangents = false ;
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
FStaticMeshConstAttributes Attributes ( MeshDescription ) ;
2021-05-05 15:07:25 -04:00
TArrayView < const FVector3f > VertexInstanceNormals = Attributes . GetVertexInstanceNormals ( ) . GetRawArray ( ) ;
TArrayView < const FVector3f > VertexInstanceTangents = Attributes . GetVertexInstanceTangents ( ) . GetRawArray ( ) ;
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
for ( const FVertexInstanceID VertexInstanceID : MeshDescription . VertexInstances ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
bHasInvalidNormals | = ( VertexInstanceNormals [ VertexInstanceID ] . IsNearlyZero ( ) | | VertexInstanceNormals [ VertexInstanceID ] . ContainsNaN ( ) ) ;
bHasInvalidTangents | = ( VertexInstanceTangents [ VertexInstanceID ] . IsNearlyZero ( ) | | VertexInstanceTangents [ VertexInstanceID ] . ContainsNaN ( ) ) ;
if ( bHasInvalidNormals & & bHasInvalidTangents )
{
break ;
}
}
}
void ClearNormalsAndTangentsData ( FMeshDescription & MeshDescription , bool bClearNormals , bool bClearTangents )
{
2022-01-15 11:30:39 -05:00
if ( ! bClearNormals & & ! bClearTangents )
2020-01-23 16:28:59 -05:00
{
return ;
}
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
FStaticMeshAttributes Attributes ( MeshDescription ) ;
2021-05-05 15:07:25 -04:00
TArrayView < FVector3f > VertexInstanceNormals = Attributes . GetVertexInstanceNormals ( ) . GetRawArray ( ) ;
TArrayView < FVector3f > VertexInstanceTangents = Attributes . GetVertexInstanceTangents ( ) . GetRawArray ( ) ;
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
TArrayView < float > VertexInstanceBinormals = Attributes . GetVertexInstanceBinormalSigns ( ) . GetRawArray ( ) ;
2020-01-23 16:28:59 -05:00
//Zero out all value that need to be recompute
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
for ( const FVertexInstanceID VertexInstanceID : MeshDescription . VertexInstances ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
if ( bClearNormals )
{
2021-11-18 14:37:34 -05:00
VertexInstanceNormals [ VertexInstanceID ] = FVector3f : : ZeroVector ;
2020-01-23 16:28:59 -05:00
}
if ( bClearTangents )
{
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
// Dump the tangents
VertexInstanceBinormals [ VertexInstanceID ] = 0.0f ;
2021-11-18 14:37:34 -05:00
VertexInstanceTangents [ VertexInstanceID ] = FVector3f : : ZeroVector ;
2020-01-23 16:28:59 -05:00
}
}
}
2021-11-18 14:37:34 -05:00
struct FNTBGroupKeyFuncs : public TDefaultMapKeyFuncs < FVector2f , FVector3f , false >
2020-01-23 16:28:59 -05:00
{
//We need to sanitize the key here to make sure -0.0f fall on the same hash then 0.0f
2022-10-29 02:59:59 -04:00
static FORCEINLINE_DEBUGGABLE uint32 GetKeyHash ( KeyInitType Key )
2020-01-23 16:28:59 -05:00
{
2021-11-18 14:37:34 -05:00
FVector2f TmpKey ;
2020-01-23 16:28:59 -05:00
TmpKey . X = FMath : : IsNearlyZero ( Key . X ) ? 0.0f : Key . X ;
TmpKey . Y = FMath : : IsNearlyZero ( Key . Y ) ? 0.0f : Key . Y ;
return FCrc : : MemCrc32 ( & TmpKey , sizeof ( TmpKey ) ) ;
}
} ;
void FStaticMeshOperations : : RecomputeNormalsAndTangentsIfNeeded ( FMeshDescription & MeshDescription , EComputeNTBsFlags ComputeNTBsOptions )
{
if ( ! EnumHasAllFlags ( ComputeNTBsOptions , EComputeNTBsFlags : : Normals | EComputeNTBsFlags : : Tangents ) )
{
bool bRecomputeNormals = false ;
bool bRecomputeTangents = false ;
2024-04-30 22:25:26 -04:00
HasInvalidVertexInstanceNormalsOrTangents ( MeshDescription , bRecomputeNormals , bRecomputeTangents ) ;
2020-01-23 16:28:59 -05:00
ComputeNTBsOptions | = ( bRecomputeNormals ? EComputeNTBsFlags : : Normals : EComputeNTBsFlags : : None ) ;
ComputeNTBsOptions | = ( bRecomputeTangents ? EComputeNTBsFlags : : Tangents : EComputeNTBsFlags : : None ) ;
}
if ( EnumHasAnyFlags ( ComputeNTBsOptions , EComputeNTBsFlags : : Normals | EComputeNTBsFlags : : Tangents ) )
{
ComputeTangentsAndNormals ( MeshDescription , ComputeNTBsOptions ) ;
}
}
void FStaticMeshOperations : : ComputeTangentsAndNormals ( FMeshDescription & MeshDescription , EComputeNTBsFlags ComputeNTBsOptions )
{
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : ComputeTangentsAndNormals ) ;
//For each vertex compute the normals for every connected edges that are smooth between hard edges
// H A B
// \ || /
// G -- ** -- C
/ / / / | \
// F E D
//
// The double ** are the vertex, the double line are hard edges, the single line are soft edge.
// A and F are hard, all other edges are soft. The goal is to compute two average normals one from
// A to F and a second from F to A. Then we can set the vertex instance normals accordingly.
// First normal(A to F) = Normalize(A+B+C+D+E+F)
// Second normal(F to A) = Normalize(F+G+H+A)
// We found the connected edge using the triangle that share edges
struct FTriangleCornerData
{
FVertexInstanceID VertexInstanceID ;
float CornerAngle ;
} ;
struct FTriangleData
{
public :
//The area of the triangle
float Area ;
//Set the corner angle data for a FVertexInstanceID
void SetCornerAngleData ( FVertexInstanceID VertexInstanceID , float CornerAngle , int32 CornerIndex )
{
CornerAngleDatas [ CornerIndex ] . VertexInstanceID = VertexInstanceID ;
CornerAngleDatas [ CornerIndex ] . CornerAngle = CornerAngle ;
}
//Get the angle for the FVertexInstanceID
float GetCornerAngle ( FVertexInstanceID VertexInstanceID )
{
for ( int32 CornerIndex = 0 ; CornerIndex < 3 ; + + CornerIndex )
{
if ( CornerAngleDatas [ CornerIndex ] . VertexInstanceID = = VertexInstanceID )
{
return CornerAngleDatas [ CornerIndex ] . CornerAngle ;
}
}
//We should always found a valid VertexInstanceID
check ( false ) ;
return 0.0f ;
}
private :
//The data for each corner
FTriangleCornerData CornerAngleDatas [ 3 ] ;
} ;
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
#if 0
2020-01-23 16:28:59 -05:00
//Make sure the meshdescription is triangulate
if ( MeshDescription . Triangles ( ) . Num ( ) < MeshDescription . Polygons ( ) . Num ( ) )
{
//Triangulate the mesh, we compute the normals on triangle not on polygon.
MeshDescription . TriangulateMesh ( ) ;
}
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
# endif
2020-01-23 16:28:59 -05:00
2021-06-09 17:26:10 -04:00
if ( MeshDescription . Triangles ( ) . Num ( ) = = 0 )
{
return ;
}
2020-01-23 16:28:59 -05:00
const bool bForceComputeNormals = EnumHasAllFlags ( ComputeNTBsOptions , EComputeNTBsFlags : : Normals ) ;
const bool bForceComputeTangent = EnumHasAnyFlags ( ComputeNTBsOptions , EComputeNTBsFlags : : Normals | EComputeNTBsFlags : : Tangents ) ;
const bool bComputeTangentWithMikkTSpace = bForceComputeTangent & & EnumHasAllFlags ( ComputeNTBsOptions , EComputeNTBsFlags : : UseMikkTSpace ) ;
const bool bComputeWeightedNormals = EnumHasAllFlags ( ComputeNTBsOptions , EComputeNTBsFlags : : WeightedNTBs ) ;
//Clear any data we want to force-recompute since the following code actually look for any invalid data and recompute it.
ClearNormalsAndTangentsData ( MeshDescription , bForceComputeNormals , bForceComputeTangent ) ;
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
// Going to iterate over all triangles, so mandate that the triangle elements are compact, i.e. there are no holes
const int32 NumTriangles = MeshDescription . Triangles ( ) . Num ( ) ;
check ( MeshDescription . Triangles ( ) . GetArraySize ( ) = = NumTriangles ) ;
2020-07-16 08:23:15 -04:00
// Compute the weight (area and angle) for each triangles
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
TArray < FTriangleData > TriangleDatas ;
TriangleDatas . SetNum ( NumTriangles ) ;
2020-01-23 16:28:59 -05:00
if ( bComputeWeightedNormals )
{
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
FStaticMeshAttributes Attributes ( MeshDescription ) ;
2021-05-05 15:07:25 -04:00
TArrayView < const FVector3f > VertexPositions = Attributes . GetVertexPositions ( ) . GetRawArray ( ) ;
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
TArrayView < const FVertexID > TriVertexIDs = Attributes . GetTriangleVertexIndices ( ) . GetRawArray ( ) ;
TArrayView < const FVertexInstanceID > TriVertexInstanceIDs = Attributes . GetTriangleVertexInstanceIndices ( ) . GetRawArray ( ) ;
2020-01-23 16:28:59 -05:00
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
TriangleDatas . Reserve ( NumTriangles ) ;
for ( int32 Index = 0 , TriIndex = 0 ; Index < NumTriangles ; Index + + , TriIndex + = 3 )
2020-02-04 19:04:31 -05:00
{
2022-10-03 19:39:31 -04:00
const FVector3f PointA ( VertexPositions [ TriVertexIDs [ TriIndex + 0 ] ] ) ;
const FVector3f PointB ( VertexPositions [ TriVertexIDs [ TriIndex + 1 ] ] ) ;
const FVector3f PointC ( VertexPositions [ TriVertexIDs [ TriIndex + 2 ] ] ) ;
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
FTriangleData & TriangleData = TriangleDatas [ Index ] ;
2020-01-23 16:28:59 -05:00
TriangleData . Area = TriangleUtilities : : ComputeTriangleArea ( PointA , PointB , PointC ) ;
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
TriangleData . SetCornerAngleData ( TriVertexInstanceIDs [ TriIndex + 0 ] , TriangleUtilities : : ComputeTriangleCornerAngle ( PointA , PointB , PointC ) , 0 ) ;
TriangleData . SetCornerAngleData ( TriVertexInstanceIDs [ TriIndex + 1 ] , TriangleUtilities : : ComputeTriangleCornerAngle ( PointB , PointC , PointA ) , 1 ) ;
TriangleData . SetCornerAngleData ( TriVertexInstanceIDs [ TriIndex + 2 ] , TriangleUtilities : : ComputeTriangleCornerAngle ( PointC , PointA , PointB ) , 2 ) ;
2020-01-23 16:28:59 -05:00
}
}
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
// Ensure certain indexers are built in anticipation
MeshDescription . BuildVertexIndexers ( ) ;
MeshDescription . BuildEdgeIndexers ( ) ;
// Going to iterate over all vertices, so mandate that the vertex elements are compact, i.e. there are no holes
const int32 NumVertices = MeshDescription . Vertices ( ) . Num ( ) ;
check ( MeshDescription . Vertices ( ) . GetArraySize ( ) = = NumVertices ) ;
2020-01-23 16:28:59 -05:00
// Split work in batch to reduce call and allocation overhead
const int32 BatchSize = 128 * 1024 ;
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
const int32 BatchCount = ( NumVertices + BatchSize - 1 ) / BatchSize ;
2020-01-23 16:28:59 -05:00
//Iterate all vertex to compute normals for all vertex instance
2022-02-23 19:25:03 -05:00
ParallelFor ( TEXT ( " ComputeTangentsAndNormals.PF " ) , BatchCount , 1 ,
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
[ NumVertices , BatchSize , bComputeTangentWithMikkTSpace , bComputeWeightedNormals , & MeshDescription , & TriangleDatas ] ( int32 BatchIndex )
2020-02-04 19:04:31 -05:00
{
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
FStaticMeshAttributes Attributes ( MeshDescription ) ;
2020-01-23 16:28:59 -05:00
2024-03-04 21:06:34 -05:00
TArrayView < const FVector2f > VertexUVs ;
2021-05-05 15:07:25 -04:00
TArrayView < const FVector3f > TriangleNormals = Attributes . GetTriangleNormals ( ) . GetRawArray ( ) ;
TArrayView < const FVector3f > TriangleTangents = Attributes . GetTriangleTangents ( ) . GetRawArray ( ) ;
TArrayView < const FVector3f > TriangleBinormals = Attributes . GetTriangleBinormals ( ) . GetRawArray ( ) ;
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
TArrayView < const bool > EdgeHardnesses = Attributes . GetEdgeHardnesses ( ) . GetRawArray ( ) ;
2020-01-23 16:28:59 -05:00
2021-05-05 15:07:25 -04:00
TArrayView < FVector3f > VertexNormals = Attributes . GetVertexInstanceNormals ( ) . GetRawArray ( ) ;
TArrayView < FVector3f > VertexTangents = Attributes . GetVertexInstanceTangents ( ) . GetRawArray ( ) ;
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
TArrayView < float > VertexBinormalSigns = Attributes . GetVertexInstanceBinormalSigns ( ) . GetRawArray ( ) ;
2024-03-04 21:06:34 -05:00
// If the mesh has no UVs, average all tangents/bi-normals for a given vertex, rather than try to maintain
// the UV flow.
if ( Attributes . GetVertexInstanceUVs ( ) . GetNumChannels ( ) > 0 )
{
// Use UV0 as the base. Same as with ComputeTriangleTangentsAndNormals
VertexUVs = Attributes . GetVertexInstanceUVs ( ) . GetRawArray ( 0 ) ;
}
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
check ( TriangleNormals . Num ( ) > 0 ) ;
check ( TriangleTangents . Num ( ) > 0 ) ;
check ( TriangleBinormals . Num ( ) > 0 ) ;
2020-01-23 16:28:59 -05:00
//Reuse containers between iterations to reduce allocations
2021-11-18 14:37:34 -05:00
TMap < FVector2f , FVector3f , FDefaultSetAllocator , FNTBGroupKeyFuncs > GroupTangent ;
TMap < FVector2f , FVector3f , FDefaultSetAllocator , FNTBGroupKeyFuncs > GroupBiNormal ;
2020-01-23 16:28:59 -05:00
TMap < FTriangleID , FVertexInfo > VertexInfoMap ;
TArray < TArray < FTriangleID , TInlineAllocator < 8 > > > Groups ;
2024-10-15 17:50:08 -04:00
TSet < FTriangleID > ConsumedTriangle ;
2020-01-23 16:28:59 -05:00
TArray < FTriangleID > PolygonQueue ;
TArray < FVertexInstanceID > VertexInstanceInGroup ;
VertexInfoMap . Reserve ( 20 ) ;
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 StartIndex = BatchIndex * BatchSize ;
int32 LastIndex = FMath : : Min ( StartIndex + BatchSize , NumVertices ) ;
for ( int32 Index = StartIndex ; Index < LastIndex ; + + Index )
2020-01-23 16:28:59 -05:00
{
VertexInfoMap . Reset ( ) ;
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
const FVertexID VertexID ( Index ) ;
2020-01-23 16:28:59 -05:00
bool bPointHasAllTangents = true ;
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
// Fill the VertexInfoMap
2022-01-06 16:44:09 +00:00
for ( const FEdgeID & EdgeID : MeshDescription . GetVertexConnectedEdgeIDs ( VertexID ) )
2020-01-23 16:28:59 -05:00
{
2022-01-06 16:44:09 +00:00
for ( const FTriangleID & TriangleID : MeshDescription . GetEdgeConnectedTriangleIDs ( EdgeID ) )
2020-01-23 16:28:59 -05:00
{
FVertexInfo & VertexInfo = VertexInfoMap . FindOrAdd ( TriangleID ) ;
int32 EdgeIndex = VertexInfo . EdgeIDs . AddUnique ( EdgeID ) ;
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
if ( VertexInfo . TriangleID = = INDEX_NONE )
2020-01-23 16:28:59 -05:00
{
VertexInfo . TriangleID = TriangleID ;
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID & VertexInstanceID : MeshDescription . GetTriangleVertexInstances ( TriangleID ) )
2020-01-23 16:28:59 -05:00
{
if ( MeshDescription . GetVertexInstanceVertex ( VertexInstanceID ) = = VertexID )
{
VertexInfo . VertexInstanceID = VertexInstanceID ;
2024-03-04 21:06:34 -05:00
if ( ! VertexUVs . IsEmpty ( ) )
{
VertexInfo . UVs = VertexUVs [ VertexInstanceID ] ; // UV0
}
2020-01-23 16:28:59 -05:00
bPointHasAllTangents & = ! VertexNormals [ VertexInstanceID ] . IsNearlyZero ( ) & & ! VertexTangents [ VertexInstanceID ] . IsNearlyZero ( ) ;
if ( bPointHasAllTangents )
{
2021-11-18 14:37:34 -05:00
FVector3f TangentX = VertexTangents [ VertexInstanceID ] . GetSafeNormal ( ) ;
FVector3f TangentZ = VertexNormals [ VertexInstanceID ] . GetSafeNormal ( ) ;
FVector3f TangentY = ( FVector3f : : CrossProduct ( TangentZ , TangentX ) . GetSafeNormal ( ) * VertexBinormalSigns [ VertexInstanceID ] ) . GetSafeNormal ( ) ;
2020-01-23 16:28:59 -05:00
if ( TangentX . ContainsNaN ( ) | | TangentX . IsNearlyZero ( SMALL_NUMBER ) | |
TangentY . ContainsNaN ( ) | | TangentY . IsNearlyZero ( SMALL_NUMBER ) | |
TangentZ . ContainsNaN ( ) | | TangentZ . IsNearlyZero ( SMALL_NUMBER ) )
{
bPointHasAllTangents = false ;
}
}
break ;
}
}
}
}
}
if ( bPointHasAllTangents )
{
continue ;
}
//Build all group by recursively traverse all polygon connected to the vertex
Groups . Reset ( ) ;
ConsumedTriangle . Reset ( ) ;
2024-10-15 17:50:08 -04:00
TSet < FEdgeID > ConsumedEdges ;
2020-01-23 16:28:59 -05:00
for ( auto Kvp : VertexInfoMap )
{
if ( ConsumedTriangle . Contains ( Kvp . Key ) )
{
continue ;
}
int32 CurrentGroupIndex = Groups . AddZeroed ( ) ;
TArray < FTriangleID , TInlineAllocator < 8 > > & CurrentGroup = Groups [ CurrentGroupIndex ] ;
PolygonQueue . Reset ( ) ;
PolygonQueue . Add ( Kvp . Key ) ; //Use a queue to avoid recursive function
while ( PolygonQueue . Num ( ) > 0 )
{
2024-01-19 16:41:35 -05:00
FTriangleID CurrentPolygonID = PolygonQueue . Pop ( EAllowShrinking : : No ) ;
2020-01-23 16:28:59 -05:00
FVertexInfo & CurrentVertexInfo = VertexInfoMap . FindOrAdd ( CurrentPolygonID ) ;
CurrentGroup . AddUnique ( CurrentVertexInfo . TriangleID ) ;
2024-10-15 17:50:08 -04:00
ConsumedTriangle . Add ( CurrentVertexInfo . TriangleID ) ;
2022-01-06 16:44:09 +00:00
for ( const FEdgeID & EdgeID : CurrentVertexInfo . EdgeIDs )
2020-01-23 16:28:59 -05:00
{
2024-10-15 17:50:08 -04:00
if ( EdgeHardnesses [ EdgeID ] | | ConsumedEdges . Contains ( EdgeID ) )
2020-01-23 16:28:59 -05:00
{
2024-10-15 17:50:08 -04:00
//End of the group or non manifold edge
2020-01-23 16:28:59 -05:00
continue ;
}
2024-10-15 17:50:08 -04:00
ConsumedEdges . Add ( EdgeID ) ;
2022-01-06 16:44:09 +00:00
for ( const FTriangleID & TriangleID : MeshDescription . GetEdgeConnectedTriangleIDs ( EdgeID ) )
2020-01-23 16:28:59 -05:00
{
if ( TriangleID = = CurrentVertexInfo . TriangleID )
{
continue ;
}
//Add this polygon to the group
FVertexInfo & OtherVertexInfo = VertexInfoMap . FindOrAdd ( TriangleID ) ;
//Do not repeat polygons
if ( ! ConsumedTriangle . Contains ( OtherVertexInfo . TriangleID ) )
{
PolygonQueue . Add ( TriangleID ) ;
}
}
}
}
}
for ( const TArray < FTriangleID , TInlineAllocator < 8 > > & Group : Groups )
{
//Compute tangents data
GroupTangent . Reset ( ) ;
GroupBiNormal . Reset ( ) ;
VertexInstanceInGroup . Reset ( ) ;
2021-11-18 14:37:34 -05:00
FVector3f GroupNormal ( FVector3f : : ZeroVector ) ;
2024-03-04 21:06:34 -05:00
2022-01-06 16:44:09 +00:00
for ( const FTriangleID & TriangleID : Group )
2020-01-23 16:28:59 -05:00
{
FVertexInfo & CurrentVertexInfo = VertexInfoMap . FindOrAdd ( TriangleID ) ;
float CornerWeight = 1.0f ;
if ( bComputeWeightedNormals )
{
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
FTriangleData & TriangleData = TriangleDatas [ TriangleID ] ;
2020-01-23 16:28:59 -05:00
CornerWeight = TriangleData . Area * TriangleData . GetCornerAngle ( CurrentVertexInfo . VertexInstanceID ) ;
}
2021-11-18 14:37:34 -05:00
const FVector3f TriNormal = CornerWeight * TriangleNormals [ TriangleID ] ;
const FVector3f TriTangent = CornerWeight * TriangleTangents [ TriangleID ] ;
const FVector3f TriBinormal = CornerWeight * TriangleBinormals [ TriangleID ] ;
2020-01-23 16:28:59 -05:00
VertexInstanceInGroup . Add ( VertexInfoMap [ TriangleID ] . VertexInstanceID ) ;
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
if ( ! TriNormal . IsNearlyZero ( SMALL_NUMBER ) & & ! TriNormal . ContainsNaN ( ) )
2020-01-23 16:28:59 -05:00
{
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
GroupNormal + = TriNormal ;
2020-01-23 16:28:59 -05:00
}
if ( ! bComputeTangentWithMikkTSpace )
{
2021-11-18 14:37:34 -05:00
const FVector2f & UVs = VertexInfoMap [ TriangleID ] . UVs ;
2020-01-23 16:28:59 -05:00
bool CreateGroup = ( ! GroupTangent . Contains ( UVs ) ) ;
2021-05-05 15:07:25 -04:00
FVector3f & GroupTangentValue = GroupTangent . FindOrAdd ( UVs ) ;
FVector3f & GroupBiNormalValue = GroupBiNormal . FindOrAdd ( UVs ) ;
2020-01-23 16:28:59 -05:00
if ( CreateGroup )
{
2021-11-18 14:37:34 -05:00
GroupTangentValue = FVector3f ( 0.0f ) ;
GroupBiNormalValue = FVector3f ( 0.0f ) ;
2020-01-23 16:28:59 -05:00
}
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
if ( ! TriTangent . IsNearlyZero ( SMALL_NUMBER ) & & ! TriTangent . ContainsNaN ( ) )
2020-01-23 16:28:59 -05:00
{
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
GroupTangentValue + = TriTangent ;
2020-01-23 16:28:59 -05:00
}
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
if ( ! TriBinormal . IsNearlyZero ( SMALL_NUMBER ) & & ! TriBinormal . ContainsNaN ( ) )
2020-01-23 16:28:59 -05:00
{
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
GroupBiNormalValue + = TriBinormal ;
2020-01-23 16:28:59 -05:00
}
}
}
//////////////////////////////////////////////////////////////////////////
//Apply the group to the Mesh
GroupNormal . Normalize ( ) ;
if ( ! bComputeTangentWithMikkTSpace )
{
2024-03-04 21:06:34 -05:00
for ( auto & Kvp : GroupTangent )
2020-01-23 16:28:59 -05:00
{
Kvp . Value . Normalize ( ) ;
}
2024-03-04 21:06:34 -05:00
for ( auto & Kvp : GroupBiNormal )
2020-01-23 16:28:59 -05:00
{
Kvp . Value . Normalize ( ) ;
}
}
//Apply the average NTB on all Vertex instance
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID & VertexInstanceID : VertexInstanceInGroup )
2020-01-23 16:28:59 -05:00
{
2024-03-04 21:06:34 -05:00
const FVector2f & VertexUV = ! VertexUVs . IsEmpty ( ) ? VertexUVs [ VertexInstanceID ] : FVector2f : : ZeroVector ;
2020-01-23 16:28:59 -05:00
if ( VertexNormals [ VertexInstanceID ] . IsNearlyZero ( SMALL_NUMBER ) )
{
VertexNormals [ VertexInstanceID ] = GroupNormal ;
}
//If we are not computing the tangent with MikkTSpace, make sure the tangents are valid.
if ( ! bComputeTangentWithMikkTSpace )
{
//Avoid changing the original group value
2021-05-05 15:07:25 -04:00
FVector3f GroupTangentValue = GroupTangent [ VertexUV ] ;
FVector3f GroupBiNormalValue = GroupBiNormal [ VertexUV ] ;
2020-01-23 16:28:59 -05:00
if ( ! VertexTangents [ VertexInstanceID ] . IsNearlyZero ( SMALL_NUMBER ) )
{
GroupTangentValue = VertexTangents [ VertexInstanceID ] ;
}
2021-05-05 15:07:25 -04:00
FVector3f BiNormal ( 0.0f ) ;
2021-11-18 14:37:34 -05:00
const FVector3f & VertexNormal ( VertexNormals [ VertexInstanceID ] ) ;
2020-01-23 16:28:59 -05:00
if ( ! VertexNormal . IsNearlyZero ( SMALL_NUMBER ) & & ! VertexTangents [ VertexInstanceID ] . IsNearlyZero ( SMALL_NUMBER ) )
{
2021-05-05 15:07:25 -04:00
BiNormal = FVector3f : : CrossProduct ( VertexNormal , VertexTangents [ VertexInstanceID ] ) . GetSafeNormal ( ) * VertexBinormalSigns [ VertexInstanceID ] ;
2020-01-23 16:28:59 -05:00
}
if ( ! BiNormal . IsNearlyZero ( SMALL_NUMBER ) )
{
GroupBiNormalValue = BiNormal ;
}
// Gram-Schmidt orthogonalization
GroupBiNormalValue - = GroupTangentValue * ( GroupTangentValue | GroupBiNormalValue ) ;
GroupBiNormalValue . Normalize ( ) ;
GroupTangentValue - = VertexNormal * ( VertexNormal | GroupTangentValue ) ;
GroupTangentValue . Normalize ( ) ;
GroupBiNormalValue - = VertexNormal * ( VertexNormal | GroupBiNormalValue ) ;
GroupBiNormalValue . Normalize ( ) ;
//Set the value
VertexTangents [ VertexInstanceID ] = GroupTangentValue ;
//If the BiNormal is zero set the sign to 1.0f, inlining GetBasisDeterminantSign() to avoid depending on RenderCore.
2021-05-05 15:07:25 -04:00
VertexBinormalSigns [ VertexInstanceID ] = FMatrix44f ( GroupTangentValue , GroupBiNormalValue , VertexNormal , FVector3f : : ZeroVector ) . Determinant ( ) < 0 ? - 1.0f : + 1.0f ;
2020-01-23 16:28:59 -05:00
}
}
}
}
}
) ;
if ( bForceComputeTangent & & bComputeTangentWithMikkTSpace )
{
ComputeMikktTangents ( MeshDescription , EnumHasAnyFlags ( ComputeNTBsOptions , EComputeNTBsFlags : : IgnoreDegenerateTriangles ) ) ;
}
}
# if WITH_MIKKTSPACE
namespace MeshDescriptionMikktSpaceInterface
{
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
struct FMeshDescriptionCachedData
{
int32 NumTriangles ;
TArrayView < const FVertexID > TriangleVertexIDs ;
TArrayView < const FVertexInstanceID > TriangleVertexInstanceIDs ;
2021-05-05 15:07:25 -04:00
TArrayView < const FVector3f > VertexPositions ;
TArrayView < const FVector3f > VertexInstanceNormals ;
2021-11-18 14:37:34 -05:00
TArrayView < const FVector2f > VertexInstanceUVs ;
2021-05-05 15:07:25 -04:00
TArrayView < FVector3f > VertexInstanceTangents ;
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
TArrayView < float > VertexInstanceBinormalSigns ;
} ;
2020-01-23 16:28:59 -05:00
int MikkGetNumFaces ( const SMikkTSpaceContext * Context )
{
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
FMeshDescriptionCachedData * UserData = ( FMeshDescriptionCachedData * ) ( Context - > m_pUserData ) ;
return UserData - > NumTriangles ;
2020-01-23 16:28:59 -05:00
}
int MikkGetNumVertsOfFace ( const SMikkTSpaceContext * Context , const int FaceIdx )
{
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
FMeshDescriptionCachedData * UserData = ( FMeshDescriptionCachedData * ) ( Context - > m_pUserData ) ;
return 3 ;
2020-01-23 16:28:59 -05:00
}
void MikkGetPosition ( const SMikkTSpaceContext * Context , float Position [ 3 ] , const int FaceIdx , const int VertIdx )
{
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
FMeshDescriptionCachedData * UserData = ( FMeshDescriptionCachedData * ) ( Context - > m_pUserData ) ;
2021-05-05 15:07:25 -04:00
const FVector3f & VertexPosition = UserData - > VertexPositions [ UserData - > TriangleVertexIDs [ FaceIdx * 3 + VertIdx ] ] ;
2020-01-23 16:28:59 -05:00
Position [ 0 ] = VertexPosition . X ;
Position [ 1 ] = VertexPosition . Y ;
Position [ 2 ] = VertexPosition . Z ;
}
void MikkGetNormal ( const SMikkTSpaceContext * Context , float Normal [ 3 ] , const int FaceIdx , const int VertIdx )
{
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
FMeshDescriptionCachedData * UserData = ( FMeshDescriptionCachedData * ) ( Context - > m_pUserData ) ;
2021-05-05 15:07:25 -04:00
const FVector3f & VertexNormal = UserData - > VertexInstanceNormals [ UserData - > TriangleVertexInstanceIDs [ FaceIdx * 3 + VertIdx ] ] ;
2020-01-23 16:28:59 -05:00
Normal [ 0 ] = VertexNormal . X ;
Normal [ 1 ] = VertexNormal . Y ;
Normal [ 2 ] = VertexNormal . Z ;
}
void MikkSetTSpaceBasic ( const SMikkTSpaceContext * Context , const float Tangent [ 3 ] , const float BitangentSign , const int FaceIdx , const int VertIdx )
{
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
FMeshDescriptionCachedData * UserData = ( FMeshDescriptionCachedData * ) ( Context - > m_pUserData ) ;
const FVertexInstanceID VertexInstanceID = UserData - > TriangleVertexInstanceIDs [ FaceIdx * 3 + VertIdx ] ;
2021-11-18 14:37:34 -05:00
UserData - > VertexInstanceTangents [ VertexInstanceID ] = FVector3f ( Tangent [ 0 ] , Tangent [ 1 ] , Tangent [ 2 ] ) ;
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
UserData - > VertexInstanceBinormalSigns [ VertexInstanceID ] = - BitangentSign ;
2020-01-23 16:28:59 -05:00
}
void MikkGetTexCoord ( const SMikkTSpaceContext * Context , float UV [ 2 ] , const int FaceIdx , const int VertIdx )
{
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
FMeshDescriptionCachedData * UserData = ( FMeshDescriptionCachedData * ) ( Context - > m_pUserData ) ;
2021-11-18 14:37:34 -05:00
const FVector2f & TexCoord = UserData - > VertexInstanceUVs [ UserData - > TriangleVertexInstanceIDs [ FaceIdx * 3 + VertIdx ] ] ;
2020-01-23 16:28:59 -05:00
UV [ 0 ] = TexCoord . X ;
UV [ 1 ] = TexCoord . Y ;
}
}
# endif //#WITH_MIKKTSPACE
void FStaticMeshOperations : : ComputeMikktTangents ( FMeshDescription & MeshDescription , bool bIgnoreDegenerateTriangles )
{
# if WITH_MIKKTSPACE
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : ComputeMikktTangents ) ;
// The Mikkt interface does not handle properly polygon array with 'holes'
// Compact mesh description if this is the case
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 ( MeshDescription . NeedsCompact ( ) )
2020-01-23 16:28:59 -05:00
{
FElementIDRemappings Remappings ;
MeshDescription . Compact ( Remappings ) ;
}
2021-01-14 12:19:06 -04:00
int32 NumTriangles = MeshDescription . Triangles ( ) . Num ( ) ;
if ( NumTriangles = = 0 )
{
return ; // nothing to compute
}
2020-01-23 16:28:59 -05:00
// we can use mikktspace to calculate the tangents
SMikkTSpaceInterface MikkTInterface ;
MikkTInterface . m_getNormal = MeshDescriptionMikktSpaceInterface : : MikkGetNormal ;
MikkTInterface . m_getNumFaces = MeshDescriptionMikktSpaceInterface : : MikkGetNumFaces ;
MikkTInterface . m_getNumVerticesOfFace = MeshDescriptionMikktSpaceInterface : : MikkGetNumVertsOfFace ;
MikkTInterface . m_getPosition = MeshDescriptionMikktSpaceInterface : : MikkGetPosition ;
MikkTInterface . m_getTexCoord = MeshDescriptionMikktSpaceInterface : : MikkGetTexCoord ;
MikkTInterface . m_setTSpaceBasic = MeshDescriptionMikktSpaceInterface : : MikkSetTSpaceBasic ;
MikkTInterface . m_setTSpace = nullptr ;
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
MeshDescriptionMikktSpaceInterface : : FMeshDescriptionCachedData UserData ;
UserData . NumTriangles = MeshDescription . Triangles ( ) . Num ( ) ;
FStaticMeshAttributes Attributes ( MeshDescription ) ;
UserData . TriangleVertexIDs = Attributes . GetTriangleVertexIndices ( ) . GetRawArray ( ) ;
UserData . TriangleVertexInstanceIDs = Attributes . GetTriangleVertexInstanceIndices ( ) . GetRawArray ( ) ;
UserData . VertexPositions = Attributes . GetVertexPositions ( ) . GetRawArray ( ) ;
UserData . VertexInstanceUVs = Attributes . GetVertexInstanceUVs ( ) . GetRawArray ( 0 ) ;
UserData . VertexInstanceNormals = Attributes . GetVertexInstanceNormals ( ) . GetRawArray ( ) ;
UserData . VertexInstanceTangents = Attributes . GetVertexInstanceTangents ( ) . GetRawArray ( ) ;
UserData . VertexInstanceBinormalSigns = Attributes . GetVertexInstanceBinormalSigns ( ) . GetRawArray ( ) ;
2020-01-23 16:28:59 -05:00
SMikkTSpaceContext MikkTContext ;
MikkTContext . m_pInterface = & MikkTInterface ;
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
MikkTContext . m_pUserData = ( void * ) ( & UserData ) ;
2020-01-23 16:28:59 -05:00
MikkTContext . m_bIgnoreDegenerates = bIgnoreDegenerateTriangles ;
genTangSpaceDefault ( & MikkTContext ) ;
# else
ensureMsgf ( false , TEXT ( " MikkTSpace tangent generation is not supported on this platform. " ) ) ;
# endif //WITH_MIKKTSPACE
}
void FStaticMeshOperations : : FindOverlappingCorners ( FOverlappingCorners & OutOverlappingCorners , const FMeshDescription & MeshDescription , float ComparisonThreshold )
{
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : FindOverlappingCorners ) ;
// @todo: this should be shared with FOverlappingCorners
const FVertexInstanceArray & VertexInstanceArray = MeshDescription . VertexInstances ( ) ;
const FVertexArray & VertexArray = MeshDescription . Vertices ( ) ;
int32 NumWedges = 3 * MeshDescription . Triangles ( ) . Num ( ) ;
// Empty the old data and reserve space for new
OutOverlappingCorners . Init ( NumWedges ) ;
// Create a list of vertex Z/index pairs
TArray < MeshDescriptionOperationNamespace : : FIndexAndZ > VertIndexAndZ ;
VertIndexAndZ . Reserve ( NumWedges ) ;
2021-05-05 15:07:25 -04:00
TVertexAttributesConstRef < FVector3f > VertexPositions = MeshDescription . GetVertexPositions ( ) ;
2020-01-23 16:28:59 -05:00
int32 WedgeIndex = 0 ;
for ( const FPolygonID PolygonID : MeshDescription . Polygons ( ) . GetElementIDs ( ) )
{
2020-07-16 08:23:15 -04:00
TArrayView < const FTriangleID > TriangleIDs = MeshDescription . GetPolygonTriangles ( PolygonID ) ;
2022-01-06 16:44:09 +00:00
for ( const FTriangleID & TriangleID : TriangleIDs )
2020-01-23 16:28:59 -05:00
{
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
const FVertexInstanceID VertexInstanceID = MeshDescription . GetTriangleVertexInstance ( TriangleID , Corner ) ;
2023-05-09 05:17:49 -04:00
VertIndexAndZ . Emplace ( WedgeIndex , VertexPositions [ MeshDescription . GetVertexInstanceVertex ( VertexInstanceID ) ] ) ;
2020-01-23 16:28:59 -05:00
+ + WedgeIndex ;
}
}
}
// Sort the vertices by z value
VertIndexAndZ . Sort ( MeshDescriptionOperationNamespace : : FCompareIndexAndZ ( ) ) ;
// Search for duplicates, quickly!
for ( int32 i = 0 ; i < VertIndexAndZ . Num ( ) ; i + + )
{
// only need to search forward, since we add pairs both ways
for ( int32 j = i + 1 ; j < VertIndexAndZ . Num ( ) ; j + + )
{
if ( FMath : : Abs ( VertIndexAndZ [ j ] . Z - VertIndexAndZ [ i ] . Z ) > ComparisonThreshold )
break ; // can't be any more dups
2021-05-05 15:07:25 -04:00
const FVector3f & PositionA = * ( VertIndexAndZ [ i ] . OriginalVector ) ;
const FVector3f & PositionB = * ( VertIndexAndZ [ j ] . OriginalVector ) ;
2020-01-23 16:28:59 -05:00
if ( PositionA . Equals ( PositionB , ComparisonThreshold ) )
{
OutOverlappingCorners . Add ( VertIndexAndZ [ i ] . Index , VertIndexAndZ [ j ] . Index ) ;
OutOverlappingCorners . Add ( VertIndexAndZ [ j ] . Index , VertIndexAndZ [ i ] . Index ) ;
}
}
}
OutOverlappingCorners . FinishAdding ( ) ;
}
struct FLayoutUVMeshDescriptionView final : FLayoutUV : : IMeshView
{
FMeshDescription & MeshDescription ;
2021-05-05 15:07:25 -04:00
TVertexAttributesConstRef < FVector3f > Positions ;
TVertexInstanceAttributesConstRef < FVector3f > Normals ;
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesRef < FVector2f > TexCoords ;
2020-01-23 16:28:59 -05:00
const uint32 SrcChannel ;
const uint32 DstChannel ;
uint32 NumIndices = 0 ;
TArray < int32 > RemapVerts ;
2021-11-18 14:37:34 -05:00
TArray < FVector2f > FlattenedTexCoords ;
2020-01-23 16:28:59 -05:00
FLayoutUVMeshDescriptionView ( FMeshDescription & InMeshDescription , uint32 InSrcChannel , uint32 InDstChannel )
: MeshDescription ( InMeshDescription )
, SrcChannel ( InSrcChannel )
, DstChannel ( InDstChannel )
{
2020-07-16 08:23:15 -04:00
FStaticMeshAttributes Attributes ( InMeshDescription ) ;
Positions = Attributes . GetVertexPositions ( ) ;
Normals = Attributes . GetVertexInstanceNormals ( ) ;
TexCoords = Attributes . GetVertexInstanceUVs ( ) ;
2020-01-23 16:28:59 -05:00
uint32 NumTris = MeshDescription . Triangles ( ) . Num ( ) ;
NumIndices = NumTris * 3 ;
FlattenedTexCoords . SetNumUninitialized ( NumIndices ) ;
RemapVerts . SetNumUninitialized ( NumIndices ) ;
int32 WedgeIndex = 0 ;
for ( const FPolygonID PolygonID : MeshDescription . Polygons ( ) . GetElementIDs ( ) )
{
2020-07-16 08:23:15 -04:00
TArrayView < const FTriangleID > TriangleIDs = MeshDescription . GetPolygonTriangles ( PolygonID ) ;
2022-01-06 16:44:09 +00:00
for ( const FTriangleID & TriangleID : TriangleIDs )
2020-01-23 16:28:59 -05:00
{
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
const FVertexInstanceID VertexInstanceID = MeshDescription . GetTriangleVertexInstance ( TriangleID , Corner ) ;
FlattenedTexCoords [ WedgeIndex ] = TexCoords . Get ( VertexInstanceID , SrcChannel ) ;
RemapVerts [ WedgeIndex ] = VertexInstanceID . GetValue ( ) ;
+ + WedgeIndex ;
}
}
}
}
uint32 GetNumIndices ( ) const override { return NumIndices ; }
2021-05-05 15:07:25 -04:00
FVector3f GetPosition ( uint32 Index ) const override
2020-01-23 16:28:59 -05:00
{
FVertexInstanceID VertexInstanceID ( RemapVerts [ Index ] ) ;
FVertexID VertexID = MeshDescription . GetVertexInstanceVertex ( VertexInstanceID ) ;
return Positions [ VertexID ] ;
}
2021-05-05 15:07:25 -04:00
FVector3f GetNormal ( uint32 Index ) const override
2020-01-23 16:28:59 -05:00
{
FVertexInstanceID VertexInstanceID ( RemapVerts [ Index ] ) ;
return Normals [ VertexInstanceID ] ;
}
2021-11-18 14:37:34 -05:00
FVector2f GetInputTexcoord ( uint32 Index ) const override
2020-01-23 16:28:59 -05:00
{
return FlattenedTexCoords [ Index ] ;
}
void InitOutputTexcoords ( uint32 Num ) override
{
// If current DstChannel is out of range of the number of UVs defined by the mesh description, change the index count accordingly
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
const uint32 NumUVs = TexCoords . GetNumChannels ( ) ;
2020-01-23 16:28:59 -05:00
if ( DstChannel > = NumUVs )
{
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
TexCoords . SetNumChannels ( DstChannel + 1 ) ;
2020-01-23 16:28:59 -05:00
ensure ( false ) ; // not expecting it to get here
}
}
2021-11-18 14:37:34 -05:00
void SetOutputTexcoord ( uint32 Index , const FVector2f & Value ) override
2020-01-23 16:28:59 -05:00
{
const FVertexInstanceID VertexInstanceID ( RemapVerts [ Index ] ) ;
TexCoords . Set ( VertexInstanceID , DstChannel , Value ) ;
}
} ;
int32 FStaticMeshOperations : : GetUVChartCount ( FMeshDescription & MeshDescription , int32 SrcLightmapIndex , ELightmapUVVersion LightmapUVVersion , const FOverlappingCorners & OverlappingCorners )
{
uint32 UnusedDstIndex = - 1 ;
FLayoutUVMeshDescriptionView MeshDescriptionView ( MeshDescription , SrcLightmapIndex , UnusedDstIndex ) ;
FLayoutUV Packer ( MeshDescriptionView ) ;
Packer . SetVersion ( LightmapUVVersion ) ;
return Packer . FindCharts ( OverlappingCorners ) ;
}
bool FStaticMeshOperations : : CreateLightMapUVLayout ( FMeshDescription & MeshDescription ,
int32 SrcLightmapIndex ,
int32 DstLightmapIndex ,
int32 MinLightmapResolution ,
ELightmapUVVersion LightmapUVVersion ,
const FOverlappingCorners & OverlappingCorners )
{
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : CreateLightMapUVLayout )
FLayoutUVMeshDescriptionView MeshDescriptionView ( MeshDescription , SrcLightmapIndex , DstLightmapIndex ) ;
FLayoutUV Packer ( MeshDescriptionView ) ;
Packer . SetVersion ( LightmapUVVersion ) ;
if ( LightmapUVVersion > = ELightmapUVVersion : : ForceLightmapPadding )
{
MinLightmapResolution - = 2 ;
}
Packer . FindCharts ( OverlappingCorners ) ;
bool bPackSuccess = Packer . FindBestPacking ( MinLightmapResolution ) ;
if ( bPackSuccess )
{
Packer . CommitPackedUVs ( ) ;
}
return bPackSuccess ;
}
2023-11-20 10:37:32 -05:00
static bool GatherUniqueTriangles ( const FMeshDescription & InMeshDescription , bool bMergeIdenticalMaterials , TArray < FTriangleID > & OutRemappedTriangles , TArray < FVertexInstanceID > * OutUniqueVerts , TArray < FTriangleID > * OutDuplicateTriangles )
{
FStaticMeshConstAttributes Attributes ( InMeshDescription ) ;
TVertexInstanceAttributesConstRef < FVector2f > TexCoords = Attributes . GetVertexInstanceUVs ( ) ;
TVertexInstanceAttributesConstRef < FVector4f > VertexColors = Attributes . GetVertexInstanceColors ( ) ;
int32 NumVertexInstances = InMeshDescription . VertexInstances ( ) . Num ( ) ;
int32 NumTriangles = InMeshDescription . Triangles ( ) . Num ( ) ;
OutRemappedTriangles . Reserve ( NumTriangles ) ;
TMap < uint32 , FTriangleID > UniqueTriangles ;
if ( bMergeIdenticalMaterials )
{
UniqueTriangles . Reserve ( NumTriangles ) ;
}
if ( OutUniqueVerts )
{
OutUniqueVerts - > Reserve ( NumVertexInstances ) ;
}
if ( OutDuplicateTriangles )
{
OutDuplicateTriangles - > Reserve ( NumTriangles ) ;
}
// Compute an hash value per triangle, based on its UVs & vertices colors
auto HashAttribute = [ ] ( FVertexInstanceID InVertexInstanceID , auto InAttributeArrayRef , int32 & TriangleHash )
{
for ( int32 Channel = 0 ; Channel < InAttributeArrayRef . GetNumChannels ( ) ; + + Channel )
{
for ( const auto & Element : InAttributeArrayRef . GetArrayView ( InVertexInstanceID , Channel ) )
{
TriangleHash = HashCombine ( TriangleHash , GetTypeHash ( Element ) ) ;
}
}
} ;
for ( const FTriangleID TriangleID : InMeshDescription . Triangles ( ) . GetElementIDs ( ) )
{
const FPolygonGroupID RefPolygonGroupID = InMeshDescription . GetTrianglePolygonGroup ( TriangleID ) ;
TConstArrayView < const FVertexInstanceID > VertexInstancesIDs = InMeshDescription . GetTriangleVertexInstances ( TriangleID ) ;
TConstArrayView < const FVertexID > VertexIDs = InMeshDescription . GetTriangleVertices ( TriangleID ) ;
FTriangleID RemapTriangleID = TriangleID ;
bool bUnique = true ;
if ( bMergeIdenticalMaterials )
{
int32 TriangleHash = GetTypeHash ( RefPolygonGroupID ) ;
for ( const FVertexInstanceID & VertexInstanceID : VertexInstancesIDs )
{
// Compute hash based on UVs & vertices colors
HashAttribute ( VertexInstanceID , TexCoords , TriangleHash ) ;
HashAttribute ( VertexInstanceID , VertexColors , TriangleHash ) ;
}
FTriangleID * UniqueTriangleIDPtr = UniqueTriangles . Find ( TriangleHash ) ;
if ( UniqueTriangleIDPtr ! = nullptr )
{
RemapTriangleID = * UniqueTriangleIDPtr ;
bUnique = false ;
if ( OutDuplicateTriangles )
{
OutDuplicateTriangles - > Add ( TriangleID ) ;
}
}
else
{
UniqueTriangles . Add ( TriangleHash , TriangleID ) ;
}
}
if ( bUnique & & OutUniqueVerts )
{
OutUniqueVerts - > Append ( VertexInstancesIDs ) ;
}
OutRemappedTriangles . Add ( RemapTriangleID ) ;
}
const bool bPerformedRemapping = bMergeIdenticalMaterials & & UniqueTriangles . Num ( ) ! = OutRemappedTriangles . Num ( ) ;
return bPerformedRemapping ;
}
template < typename TSrcUVs , typename TDstUVs >
static void CopyRemappedUVs ( const FMeshDescription & InMeshDescription , const TArray < FTriangleID > & RemappedTriangles , const FElementIDRemappings * SrcElementIDRemappings , bool bCopyOnlyRemappedTrianglesUVs , const TSrcUVs & SrcUVs , TDstUVs & DstUVs )
{
int32 RemappedTrianglesIdx = 0 ;
for ( const FTriangleID TriangleID : InMeshDescription . Triangles ( ) . GetElementIDs ( ) )
{
FTriangleID RemappedTriangleID = RemappedTriangles [ RemappedTrianglesIdx ] ;
if ( ! bCopyOnlyRemappedTrianglesUVs | | RemappedTriangleID ! = TriangleID )
{
if ( SrcElementIDRemappings )
{
RemappedTriangleID = SrcElementIDRemappings - > GetRemappedTriangleID ( RemappedTriangleID ) ;
}
TConstArrayView < const FVertexInstanceID > SrcVertexInstancesIDs = InMeshDescription . GetTriangleVertexInstances ( RemappedTriangleID ) ;
TConstArrayView < const FVertexInstanceID > DstVertexInstancesIDs = InMeshDescription . GetTriangleVertexInstances ( TriangleID ) ;
for ( int32 i = 0 ; i < 3 ; i + + )
{
DstUVs [ DstVertexInstancesIDs [ i ] ] = FVector2D ( SrcUVs [ SrcVertexInstancesIDs [ i ] ] ) ;
}
}
RemappedTrianglesIdx + + ;
}
}
2021-03-10 17:06:44 -04:00
// Mesh view that will expose only unique UVs if bMergeIdenticalMaterials is provided
struct FUniqueUVMeshDescriptionView final : FLayoutUV : : IMeshView
2020-01-23 16:28:59 -05:00
{
2021-03-10 17:06:44 -04:00
const FMeshDescription & MeshDescription ;
2020-01-23 16:28:59 -05:00
2021-05-05 15:07:25 -04:00
TVertexAttributesConstRef < FVector3f > Positions ;
TVertexInstanceAttributesConstRef < FVector3f > Normals ;
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesConstRef < FVector2f > TexCoords ;
2020-01-23 16:28:59 -05:00
2022-11-04 00:01:58 -04:00
TArray < FTriangleID > RemapTriangles ;
2021-03-10 17:06:44 -04:00
TArray < FVertexInstanceID > UniqueVerts ;
2022-11-04 00:01:58 -04:00
TArray < FVector2D > & OutputTexCoords ;
bool bMustRemap ;
2021-03-10 17:06:44 -04:00
2022-11-04 00:01:58 -04:00
FUniqueUVMeshDescriptionView ( const FMeshDescription & InMeshDescription , bool bMergeIdenticalMaterials , TArray < FVector2D > & InOutTexCoords )
2021-03-10 17:06:44 -04:00
: MeshDescription ( InMeshDescription )
2022-11-04 00:01:58 -04:00
, OutputTexCoords ( InOutTexCoords )
2020-01-23 16:28:59 -05:00
{
2021-03-10 17:06:44 -04:00
FStaticMeshConstAttributes Attributes ( MeshDescription ) ;
Positions = Attributes . GetVertexPositions ( ) ;
Normals = Attributes . GetVertexInstanceNormals ( ) ;
TexCoords = Attributes . GetVertexInstanceUVs ( ) ;
2023-11-20 10:37:32 -05:00
OutputTexCoords . SetNumZeroed ( MeshDescription . VertexInstances ( ) . Num ( ) ) ;
2021-03-10 17:06:44 -04:00
2023-11-20 10:37:32 -05:00
bMustRemap = GatherUniqueTriangles ( MeshDescription , bMergeIdenticalMaterials , RemapTriangles , & UniqueVerts , nullptr ) ;
2020-01-23 16:28:59 -05:00
}
2021-03-10 17:06:44 -04:00
2022-11-04 00:01:58 -04:00
uint32 GetNumIndices ( ) const override
2021-03-10 17:06:44 -04:00
{
return UniqueVerts . Num ( ) ;
}
2021-05-05 15:07:25 -04:00
FVector3f GetPosition ( uint32 Index ) const override
2021-03-10 17:06:44 -04:00
{
FVertexID VertexID = MeshDescription . GetVertexInstanceVertex ( UniqueVerts [ Index ] ) ;
return Positions [ VertexID ] ;
}
2021-05-05 15:07:25 -04:00
FVector3f GetNormal ( uint32 Index ) const override
2021-03-10 17:06:44 -04:00
{
return Normals [ UniqueVerts [ Index ] ] ;
}
2021-11-18 14:37:34 -05:00
FVector2f GetInputTexcoord ( uint32 Index ) const override
2021-03-10 17:06:44 -04:00
{
return TexCoords . Get ( UniqueVerts [ Index ] , 0 ) ;
}
void InitOutputTexcoords ( uint32 Num ) override
{
check ( Num = = UniqueVerts . Num ( ) ) ;
}
2021-11-18 14:37:34 -05:00
void SetOutputTexcoord ( uint32 Index , const FVector2f & Value ) override
2021-03-10 17:06:44 -04:00
{
2022-11-04 00:01:58 -04:00
OutputTexCoords [ UniqueVerts [ Index ] ] = FVector2D ( Value ) ;
2021-03-10 17:06:44 -04:00
}
2022-11-04 00:01:58 -04:00
void ResolvePackedUVs ( )
2021-03-10 17:06:44 -04:00
{
2022-11-04 00:01:58 -04:00
if ( bMustRemap )
2021-03-10 17:06:44 -04:00
{
2023-11-20 10:37:32 -05:00
CopyRemappedUVs ( MeshDescription , RemapTriangles , nullptr , true , OutputTexCoords , OutputTexCoords ) ;
2021-03-10 17:06:44 -04:00
}
}
} ;
bool FStaticMeshOperations : : GenerateUniqueUVsForStaticMesh ( const FMeshDescription & MeshDescription , int32 TextureResolution , bool bMergeIdenticalMaterials , TArray < FVector2D > & OutTexCoords )
2023-11-20 10:37:32 -05:00
{
FGenerateUVOptions GenerateUVOptions ;
GenerateUVOptions . TextureResolution = TextureResolution ;
GenerateUVOptions . bMergeTrianglesWithIdenticalAttributes = bMergeIdenticalMaterials ;
GenerateUVOptions . UVMethod = EGenerateUVMethod : : Legacy ;
return GenerateUV ( MeshDescription , GenerateUVOptions , OutTexCoords ) ;
}
bool FStaticMeshOperations : : GenerateUV ( const FMeshDescription & MeshDescription , const FGenerateUVOptions & GenerateUVOptions , TArray < FVector2D > & OutTexCoords )
2021-03-10 17:06:44 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : GenerateUniqueUVsForStaticMesh )
2023-06-15 14:13:53 -04:00
TVertexInstanceAttributesConstRef < FVector2f > VertexInstanceUVs = FStaticMeshConstAttributes ( MeshDescription ) . GetVertexInstanceUVs ( ) ;
2021-03-10 17:06:44 -04:00
2023-06-15 14:13:53 -04:00
OutTexCoords . Reset ( ) ;
2020-01-23 16:28:59 -05:00
2023-06-15 14:13:53 -04:00
const bool bHasUVs = VertexInstanceUVs . GetNumElements ( ) > 0 ;
2024-07-29 15:37:01 -04:00
# if WITH_EDITOR
if ( bHasUVs & & GenerateUVOptions . UVMethod = = EGenerateUVMethod : : Legacy )
# else
if ( bHasUVs )
# endif
2020-01-23 16:28:59 -05:00
{
2023-11-20 10:37:32 -05:00
FUniqueUVMeshDescriptionView MeshDescriptionView ( MeshDescription , GenerateUVOptions . bMergeTrianglesWithIdenticalAttributes , OutTexCoords ) ;
2020-01-23 16:28:59 -05:00
2023-06-15 14:13:53 -04:00
// Find overlapping corners for UV generator. Allow some threshold - this should not produce any error in a case if resulting
// mesh will not merge these vertices.
FOverlappingCorners OverlappingCorners ( MeshDescriptionView , THRESH_POINTS_ARE_SAME ) ;
// Generate new UVs
FLayoutUV Packer ( MeshDescriptionView ) ;
int32 NumCharts = Packer . FindCharts ( OverlappingCorners ) ;
// Scale down texture resolution to speed up UV generation time
// Packing expects at least one texel per chart. This is the absolute minimum to generate valid UVs.
2023-11-20 10:37:32 -05:00
const int32 PackingResolution = FMath : : Clamp ( GenerateUVOptions . TextureResolution / 4 , 32 , 512 ) ;
2023-06-15 14:13:53 -04:00
const int32 AbsoluteMinResolution = 1 < < FMath : : CeilLogTwo ( FMath : : Sqrt ( ( float ) NumCharts ) ) ;
const int32 FinalPackingResolution = FMath : : Max ( PackingResolution , AbsoluteMinResolution ) ;
bool bPackSuccess = Packer . FindBestPacking ( FinalPackingResolution ) ;
if ( bPackSuccess )
{
Packer . CommitPackedUVs ( ) ;
MeshDescriptionView . ResolvePackedUVs ( ) ;
}
else
{
OutTexCoords . Reset ( ) ;
}
}
# if WITH_EDITOR
// Missing/invalid UVs, use the AutoUV interface
if ( OutTexCoords . IsEmpty ( ) )
{
IGeometryProcessingInterfacesModule * GeomProcInterfaces = FModuleManager : : Get ( ) . GetModulePtr < IGeometryProcessingInterfacesModule > ( " GeometryProcessingInterfaces " ) ;
2024-03-13 21:29:12 -04:00
IGeometryProcessing_MeshAutoUV * MeshAutoUV = GeomProcInterfaces ? GeomProcInterfaces - > GetMeshAutoUVImplementation ( ) : nullptr ;
if ( MeshAutoUV )
2023-06-15 14:13:53 -04:00
{
FMeshDescription MeshCopy = MeshDescription ;
2023-11-20 10:37:32 -05:00
TArray < FTriangleID > RemapTriangles ;
FElementIDRemappings ElementIDRemappings ;
bool bMustRemap = false ;
// Ensure we have properly setup TriangleUVs on our mesh
int32 UVChannelCount = MeshCopy . VertexInstanceAttributes ( ) . GetAttributeChannelCount ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
MeshCopy . SetNumUVChannels ( UVChannelCount ) ;
if ( GenerateUVOptions . bMergeTrianglesWithIdenticalAttributes )
{
TArray < FTriangleID > DuplicateTriangles ;
bMustRemap = GatherUniqueTriangles ( MeshDescription , true , RemapTriangles , nullptr , & DuplicateTriangles ) ;
if ( bMustRemap )
{
MeshCopy . DeleteTriangles ( DuplicateTriangles ) ;
MeshCopy . Compact ( ElementIDRemappings ) ;
}
}
auto GetAutoUVMethod = [ ] ( EGenerateUVMethod GenerateUVMethod ) - > IGeometryProcessing_MeshAutoUV : : EAutoUVMethod
{
switch ( GenerateUVMethod )
{
case EGenerateUVMethod : : UVAtlas : return IGeometryProcessing_MeshAutoUV : : EAutoUVMethod : : UVAtlas ;
case EGenerateUVMethod : : XAtlas : return IGeometryProcessing_MeshAutoUV : : EAutoUVMethod : : XAtlas ;
default : return IGeometryProcessing_MeshAutoUV : : EAutoUVMethod : : PatchBuilder ;
}
} ;
2023-06-15 14:13:53 -04:00
IGeometryProcessing_MeshAutoUV : : FOptions Options = MeshAutoUV - > ConstructDefaultOptions ( ) ;
2023-11-20 10:37:32 -05:00
Options . Method = GetAutoUVMethod ( GenerateUVOptions . UVMethod ) ;
2023-06-15 14:13:53 -04:00
IGeometryProcessing_MeshAutoUV : : FResults Results ;
MeshAutoUV - > GenerateUVs ( MeshCopy , Options , Results ) ;
if ( Results . ResultCode = = IGeometryProcessing_MeshAutoUV : : EResultCode : : Success )
{
TVertexInstanceAttributesConstRef < FVector2f > TexCoords ;
FStaticMeshConstAttributes AttributesCopy ( MeshCopy ) ;
TexCoords = AttributesCopy . GetVertexInstanceUVs ( ) ;
2023-11-20 10:37:32 -05:00
OutTexCoords . SetNumUninitialized ( MeshDescription . VertexInstances ( ) . Num ( ) ) ;
2023-06-15 14:13:53 -04:00
2023-11-20 10:37:32 -05:00
if ( bMustRemap )
{
CopyRemappedUVs ( MeshDescription , RemapTriangles , & ElementIDRemappings , false , TexCoords , OutTexCoords ) ;
}
else
{
int32 VertexInstanceIndex = 0 ;
for ( const FVertexInstanceID VertexInstanceID : MeshCopy . VertexInstances ( ) . GetElementIDs ( ) )
{
OutTexCoords [ VertexInstanceIndex ] = FVector2D ( TexCoords . Get ( VertexInstanceID , 0 ) ) ;
VertexInstanceIndex + + ;
}
}
2023-06-15 14:13:53 -04:00
}
}
}
# endif
check ( OutTexCoords . IsEmpty ( ) | | OutTexCoords . Num ( ) = = MeshDescription . VertexInstances ( ) . Num ( ) ) ;
return ! OutTexCoords . IsEmpty ( ) ;
2020-01-23 16:28:59 -05:00
}
bool FStaticMeshOperations : : AddUVChannel ( FMeshDescription & MeshDescription )
{
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesRef < FVector2f > VertexInstanceUVs = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector2f > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
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
if ( VertexInstanceUVs . GetNumChannels ( ) > = MAX_MESH_TEXTURE_COORDS )
2020-01-23 16:28:59 -05:00
{
UE_LOG ( LogStaticMeshOperations , Error , TEXT ( " AddUVChannel: Cannot add UV channel. Maximum number of UV channels reached (%d). " ) , MAX_MESH_TEXTURE_COORDS ) ;
return false ;
}
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 ( VertexInstanceUVs . GetNumChannels ( ) + 1 ) ;
2020-01-23 16:28:59 -05:00
return true ;
}
bool FStaticMeshOperations : : InsertUVChannel ( FMeshDescription & MeshDescription , int32 UVChannelIndex )
{
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesRef < FVector2f > VertexInstanceUVs = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector2f > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
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
if ( UVChannelIndex < 0 | | UVChannelIndex > VertexInstanceUVs . GetNumChannels ( ) )
2020-01-23 16:28:59 -05:00
{
UE_LOG ( LogStaticMeshOperations , Error , TEXT ( " InsertUVChannel: Cannot insert UV channel. Given UV channel index %d is out of bounds. " ) , UVChannelIndex ) ;
return false ;
}
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
if ( VertexInstanceUVs . GetNumChannels ( ) > = MAX_MESH_TEXTURE_COORDS )
2020-01-23 16:28:59 -05:00
{
UE_LOG ( LogStaticMeshOperations , Error , TEXT ( " InsertUVChannel: Cannot insert UV channel. Maximum number of UV channels reached (%d). " ) , MAX_MESH_TEXTURE_COORDS ) ;
return false ;
}
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 . InsertChannel ( UVChannelIndex ) ;
2020-01-23 16:28:59 -05:00
return true ;
}
bool FStaticMeshOperations : : RemoveUVChannel ( FMeshDescription & MeshDescription , int32 UVChannelIndex )
{
2021-11-18 14:37:34 -05:00
TVertexInstanceAttributesRef < FVector2f > VertexInstanceUVs = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector2f > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
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
if ( VertexInstanceUVs . GetNumChannels ( ) = = 1 )
2020-01-23 16:28:59 -05:00
{
UE_LOG ( LogStaticMeshOperations , Error , TEXT ( " RemoveUVChannel: Cannot remove UV channel. There must be at least one channel. " ) ) ;
return false ;
}
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
if ( UVChannelIndex < 0 | | UVChannelIndex > = VertexInstanceUVs . GetNumChannels ( ) )
2020-01-23 16:28:59 -05:00
{
UE_LOG ( LogStaticMeshOperations , Error , TEXT ( " RemoveUVChannel: Cannot remove UV channel. Given UV channel index %d is out of bounds. " ) , UVChannelIndex ) ;
return false ;
}
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 . RemoveChannel ( UVChannelIndex ) ;
2020-01-23 16:28:59 -05:00
return true ;
}
void FStaticMeshOperations : : GeneratePlanarUV ( const FMeshDescription & MeshDescription , const FUVMapParameters & Params , TMap < FVertexInstanceID , FVector2D > & OutTexCoords )
{
// Project along X-axis (left view), UV along Z Y axes
2022-02-02 07:59:31 -05:00
FVector U = FVector : : UpVector ;
FVector V = FVector : : RightVector ;
2020-01-23 16:28:59 -05:00
2021-05-05 15:07:25 -04:00
TMeshAttributesConstRef < FVertexID , FVector3f > VertexPositions = MeshDescription . GetVertexPositions ( ) ;
2020-01-23 16:28:59 -05:00
OutTexCoords . Reserve ( MeshDescription . VertexInstances ( ) . Num ( ) ) ;
2022-02-02 07:59:31 -05:00
FVector Size ( Params . Size * Params . Scale ) ;
FVector Offset = Params . Position - Size / 2.f ;
2020-01-23 16:28:59 -05:00
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID VertexInstanceID : MeshDescription . VertexInstances ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
const FVertexID VertexID = MeshDescription . GetVertexInstanceVertex ( VertexInstanceID ) ;
2022-02-02 07:59:31 -05:00
FVector Vertex ( VertexPositions [ VertexID ] ) ;
2020-01-23 16:28:59 -05:00
// Apply the gizmo transforms
Vertex = Params . Rotation . RotateVector ( Vertex ) ;
Vertex - = Offset ;
Vertex / = Size ;
2022-02-02 07:59:31 -05:00
float UCoord = FVector : : DotProduct ( Vertex , U ) * Params . UVTile . X ;
float VCoord = FVector : : DotProduct ( Vertex , V ) * Params . UVTile . Y ;
2020-01-23 16:28:59 -05:00
OutTexCoords . Add ( VertexInstanceID , FVector2D ( UCoord , VCoord ) ) ;
}
}
void FStaticMeshOperations : : GenerateCylindricalUV ( FMeshDescription & MeshDescription , const FUVMapParameters & Params , TMap < FVertexInstanceID , FVector2D > & OutTexCoords )
{
2022-02-02 07:59:31 -05:00
FVector3f Size ( Params . Size * Params . Scale ) ; //LWC_TODO: Precision loss
FVector3f Offset ( Params . Position ) ; //LWC_TODO: Precision loss
2020-01-23 16:28:59 -05:00
// Cylinder along X-axis, counterclockwise from -Y axis as seen from left view
2021-11-18 14:37:34 -05:00
FVector3f V = FVector3f : : ForwardVector ;
2020-01-23 16:28:59 -05:00
Offset . X - = Size . X / 2.f ;
2021-05-05 15:07:25 -04:00
TMeshAttributesConstRef < FVertexID , FVector3f > VertexPositions = MeshDescription . GetVertexPositions ( ) ;
2020-01-23 16:28:59 -05:00
OutTexCoords . Reserve ( MeshDescription . VertexInstances ( ) . Num ( ) ) ;
const float AngleOffset = PI ; // offset to get the same result as in 3dsmax
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID VertexInstanceID : MeshDescription . VertexInstances ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
const FVertexID VertexID = MeshDescription . GetVertexInstanceVertex ( VertexInstanceID ) ;
2021-11-18 14:37:34 -05:00
FVector3f Vertex = VertexPositions [ VertexID ] ;
2020-01-23 16:28:59 -05:00
// Apply the gizmo transforms
2022-02-02 07:59:31 -05:00
Vertex = FVector3f ( Params . Rotation . RotateVector ( FVector3d ( Vertex ) ) ) ;
2020-01-23 16:28:59 -05:00
Vertex - = Offset ;
Vertex / = Size ;
float Angle = FMath : : Atan2 ( Vertex . Z , Vertex . Y ) ;
Angle + = AngleOffset ;
Angle * = Params . UVTile . X ;
float UCoord = Angle / ( 2 * PI ) ;
2021-11-18 14:37:34 -05:00
float VCoord = FVector3f : : DotProduct ( Vertex , V ) * Params . UVTile . Y ;
2020-01-23 16:28:59 -05:00
OutTexCoords . Add ( VertexInstanceID , FVector2D ( UCoord , VCoord ) ) ;
}
// Fix the UV coordinates for triangles at the seam where the angle wraps around
2022-01-06 16:44:09 +00:00
for ( const FPolygonID PolygonID : MeshDescription . Polygons ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
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
TArray < FVertexInstanceID , TInlineAllocator < 4 > > VertexInstances = MeshDescription . GetPolygonVertexInstances < TInlineAllocator < 4 > > ( PolygonID ) ;
2020-01-23 16:28:59 -05:00
int32 NumInstances = VertexInstances . Num ( ) ;
if ( NumInstances > = 2 )
{
for ( int32 StartIndex = 0 ; StartIndex < NumInstances ; + + StartIndex )
{
int32 EndIndex = StartIndex + 1 ;
if ( EndIndex > = NumInstances )
{
EndIndex = EndIndex % NumInstances ;
}
const FVector2D & StartUV = OutTexCoords [ VertexInstances [ StartIndex ] ] ;
FVector2D & EndUV = OutTexCoords [ VertexInstances [ EndIndex ] ] ;
// TODO: Improve fix for UVTile other than 1
float Threshold = 0.5f / Params . UVTile . X ;
if ( FMath : : Abs ( EndUV . X - StartUV . X ) > Threshold )
{
// Fix the U coordinate to get the texture go counterclockwise
if ( EndUV . X > Threshold )
{
if ( EndUV . X > = 1.f )
{
EndUV . X - = 1.f ;
}
}
else
{
if ( EndUV . X < = 0 )
{
EndUV . X + = 1.f ;
}
}
}
}
}
}
}
void FStaticMeshOperations : : GenerateBoxUV ( const FMeshDescription & MeshDescription , const FUVMapParameters & Params , TMap < FVertexInstanceID , FVector2D > & OutTexCoords )
{
2022-02-02 07:59:31 -05:00
FVector3f Size ( Params . Size * Params . Scale ) ; //LWC_TODO: Precision loss
2021-11-18 14:37:34 -05:00
FVector3f HalfSize = Size / 2.0f ;
2020-01-23 16:28:59 -05:00
2021-05-05 15:07:25 -04:00
TMeshAttributesConstRef < FVertexID , FVector3f > VertexPositions = MeshDescription . GetVertexPositions ( ) ;
2020-01-23 16:28:59 -05:00
OutTexCoords . Reserve ( MeshDescription . VertexInstances ( ) . Num ( ) ) ;
// Setup the UVs such that the mapping is from top-left to bottom-right when viewed orthographically
2021-11-18 14:37:34 -05:00
TArray < TPair < FVector3f , FVector3f > > PlaneUVs ;
PlaneUVs . Add ( TPair < FVector3f , FVector3f > ( FVector3f : : ForwardVector , FVector3f : : RightVector ) ) ; // Top view
PlaneUVs . Add ( TPair < FVector3f , FVector3f > ( FVector3f : : BackwardVector , FVector3f : : RightVector ) ) ; // Bottom view
PlaneUVs . Add ( TPair < FVector3f , FVector3f > ( FVector3f : : ForwardVector , FVector3f : : DownVector ) ) ; // Right view
PlaneUVs . Add ( TPair < FVector3f , FVector3f > ( FVector3f : : BackwardVector , FVector3f : : DownVector ) ) ; // Left view
PlaneUVs . Add ( TPair < FVector3f , FVector3f > ( FVector3f : : LeftVector , FVector3f : : DownVector ) ) ; // Front view
PlaneUVs . Add ( TPair < FVector3f , FVector3f > ( FVector3f : : RightVector , FVector3f : : DownVector ) ) ; // Back view
2020-01-23 16:28:59 -05:00
2021-11-18 14:37:34 -05:00
TArray < FPlane4f > BoxPlanes ;
2022-02-02 07:59:31 -05:00
const FVector3f Center ( Params . Position ) ; //LWC_TODO: Precision loss
2020-01-23 16:28:59 -05:00
2021-11-18 14:37:34 -05:00
BoxPlanes . Add ( FPlane4f ( Center + FVector3f ( 0 , 0 , HalfSize . Z ) , FVector3f : : UpVector ) ) ; // Top plane
BoxPlanes . Add ( FPlane4f ( Center - FVector3f ( 0 , 0 , HalfSize . Z ) , FVector3f : : DownVector ) ) ; // Bottom plane
BoxPlanes . Add ( FPlane4f ( Center + FVector3f ( 0 , HalfSize . Y , 0 ) , FVector3f : : RightVector ) ) ; // Right plane
BoxPlanes . Add ( FPlane4f ( Center - FVector3f ( 0 , HalfSize . Y , 0 ) , FVector3f : : LeftVector ) ) ; // Left plane
BoxPlanes . Add ( FPlane4f ( Center + FVector3f ( HalfSize . X , 0 , 0 ) , FVector3f : : ForwardVector ) ) ; // Front plane
BoxPlanes . Add ( FPlane4f ( Center - FVector3f ( HalfSize . X , 0 , 0 ) , FVector3f : : BackwardVector ) ) ; // Back plane
2020-01-23 16:28:59 -05:00
// For each polygon, find the box plane that best matches the polygon normal
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
for ( const FTriangleID TriangleID : MeshDescription . Triangles ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
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
TArrayView < const FVertexID > Vertices = MeshDescription . GetTriangleVertices ( TriangleID ) ;
TArrayView < const FVertexInstanceID > VertexInstances = MeshDescription . GetTriangleVertexInstances ( TriangleID ) ;
2020-01-23 16:28:59 -05:00
2021-11-18 14:37:34 -05:00
FVector3f Vertex0 = VertexPositions [ Vertices [ 0 ] ] ;
FVector3f Vertex1 = VertexPositions [ Vertices [ 1 ] ] ;
FVector3f Vertex2 = VertexPositions [ Vertices [ 2 ] ] ;
2020-01-23 16:28:59 -05:00
2021-11-18 14:37:34 -05:00
FPlane4f PolygonPlane ( Vertex0 , Vertex2 , Vertex1 ) ;
2020-01-23 16:28:59 -05:00
// Find the box plane that is most aligned with the polygon plane
// TODO: Also take the distance between the planes into consideration
float MaxProj = 0.f ;
int32 BestPlaneIndex = 0 ;
for ( int32 Index = 0 ; Index < BoxPlanes . Num ( ) ; + + Index )
{
2021-11-18 14:37:34 -05:00
float Proj = FVector3f : : DotProduct ( BoxPlanes [ Index ] , PolygonPlane ) ;
2020-01-23 16:28:59 -05:00
if ( Proj > MaxProj )
{
MaxProj = Proj ;
BestPlaneIndex = Index ;
}
}
2021-11-18 14:37:34 -05:00
FVector3f U = PlaneUVs [ BestPlaneIndex ] . Key ;
FVector3f V = PlaneUVs [ BestPlaneIndex ] . Value ;
2022-02-02 07:59:31 -05:00
FVector3f Offset = FVector3f ( Params . Position ) - HalfSize * ( U + V ) ;
2020-01-23 16:28:59 -05:00
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID & VertexInstanceID : VertexInstances )
2020-01-23 16:28:59 -05:00
{
const FVertexID VertexID = MeshDescription . GetVertexInstanceVertex ( VertexInstanceID ) ;
2021-11-18 14:37:34 -05:00
FVector3f Vertex = VertexPositions [ VertexID ] ;
2020-01-23 16:28:59 -05:00
// Apply the gizmo transforms
2022-02-02 07:59:31 -05:00
Vertex = FVector3f ( Params . Rotation . RotateVector ( FVector3d ( Vertex ) ) ) ;
2020-01-23 16:28:59 -05:00
Vertex - = Offset ;
2021-01-21 16:22:06 -04:00
// Normalize coordinates
Vertex . X = FMath : : IsNearlyZero ( Size . X ) ? 0.0f : Vertex . X / Size . X ;
Vertex . Y = FMath : : IsNearlyZero ( Size . Y ) ? 0.0f : Vertex . Y / Size . Y ;
Vertex . Z = FMath : : IsNearlyZero ( Size . Z ) ? 0.0f : Vertex . Z / Size . Z ;
2020-01-23 16:28:59 -05:00
2021-11-18 14:37:34 -05:00
float UCoord = FVector3f : : DotProduct ( Vertex , U ) * Params . UVTile . X ;
float VCoord = FVector3f : : DotProduct ( Vertex , V ) * Params . UVTile . Y ;
2020-01-23 16:28:59 -05:00
OutTexCoords . Add ( VertexInstanceID , FVector2D ( UCoord , VCoord ) ) ;
}
}
}
void FStaticMeshOperations : : SwapPolygonPolygonGroup ( FMeshDescription & MeshDescription , int32 SectionIndex , int32 TriangleIndexStart , int32 TriangleIndexEnd , bool bRemoveEmptyPolygonGroup )
{
int32 TriangleIndex = 0 ;
TPolygonGroupAttributesRef < FName > PolygonGroupNames = MeshDescription . PolygonGroupAttributes ( ) . GetAttributesRef < FName > ( MeshAttribute : : PolygonGroup : : ImportedMaterialSlotName ) ;
FPolygonGroupID TargetPolygonGroupID ( SectionIndex ) ;
if ( ! bRemoveEmptyPolygonGroup )
{
while ( ! MeshDescription . PolygonGroups ( ) . IsValid ( TargetPolygonGroupID ) )
{
TargetPolygonGroupID = MeshDescription . CreatePolygonGroup ( ) ;
PolygonGroupNames [ TargetPolygonGroupID ] = FName ( * ( TEXT ( " SwapPolygonMaterialSlotName_ " ) + FString : : FromInt ( TargetPolygonGroupID . GetValue ( ) ) ) ) ;
TargetPolygonGroupID = FPolygonGroupID ( SectionIndex ) ;
}
}
else
{
//This will not follow the SectionIndex value if the value is greater then the number of section (do not use this when merging meshes)
if ( ! MeshDescription . PolygonGroups ( ) . IsValid ( TargetPolygonGroupID ) )
{
TargetPolygonGroupID = MeshDescription . CreatePolygonGroup ( ) ;
PolygonGroupNames [ TargetPolygonGroupID ] = FName ( * ( TEXT ( " SwapPolygonMaterialSlotName_ " ) + FString : : FromInt ( TargetPolygonGroupID . GetValue ( ) ) ) ) ;
}
}
for ( const FPolygonID PolygonID : MeshDescription . Polygons ( ) . GetElementIDs ( ) )
{
2020-07-16 08:23:15 -04:00
int32 TriangleCount = MeshDescription . GetPolygonTriangles ( PolygonID ) . Num ( ) ;
2020-01-23 16:28:59 -05:00
if ( TriangleIndex > = TriangleIndexStart & & TriangleIndex < TriangleIndexEnd )
{
check ( TriangleIndex + ( TriangleCount - 1 ) < TriangleIndexEnd ) ;
FPolygonGroupID OldpolygonGroupID = MeshDescription . GetPolygonPolygonGroup ( PolygonID ) ;
if ( OldpolygonGroupID ! = TargetPolygonGroupID )
{
MeshDescription . SetPolygonPolygonGroup ( PolygonID , TargetPolygonGroupID ) ;
2020-07-16 08:23:15 -04:00
if ( bRemoveEmptyPolygonGroup & & MeshDescription . GetPolygonGroupPolygonIDs ( OldpolygonGroupID ) . Num ( ) < 1 )
2020-01-23 16:28:59 -05:00
{
MeshDescription . DeletePolygonGroup ( OldpolygonGroupID ) ;
}
}
}
TriangleIndex + = TriangleCount ;
}
}
bool FStaticMeshOperations : : HasVertexColor ( const FMeshDescription & MeshDescription )
{
2021-09-22 10:01:48 -04:00
TVertexInstanceAttributesConstRef < FVector4f > VertexInstanceColors = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector4f > ( MeshAttribute : : VertexInstance : : Color ) ;
2020-01-23 16:28:59 -05:00
bool bHasVertexColor = false ;
2021-11-18 14:37:34 -05:00
FVector4f WhiteColor ( FLinearColor : : White ) ;
2022-01-06 16:44:09 +00:00
for ( const FVertexInstanceID VertexInstanceID : MeshDescription . VertexInstances ( ) . GetElementIDs ( ) )
2020-01-23 16:28:59 -05:00
{
if ( VertexInstanceColors [ VertexInstanceID ] ! = WhiteColor )
{
bHasVertexColor = true ;
break ;
}
}
return bHasVertexColor ;
}
void FStaticMeshOperations : : BuildWeldedVertexIDRemap ( const FMeshDescription & MeshDescription , const float WeldingThreshold , TMap < FVertexID , FVertexID > & OutVertexIDRemap )
{
2021-05-05 15:07:25 -04:00
TVertexAttributesConstRef < FVector3f > VertexPositions = MeshDescription . GetVertexPositions ( ) ;
2020-01-23 16:28:59 -05:00
int32 NumVertex = MeshDescription . Vertices ( ) . Num ( ) ;
OutVertexIDRemap . Reserve ( NumVertex ) ;
// Create a list of vertex Z/index pairs
TArray < MeshDescriptionOperationNamespace : : FIndexAndZ > VertIndexAndZ ;
VertIndexAndZ . Reserve ( NumVertex ) ;
for ( const FVertexID VertexID : MeshDescription . Vertices ( ) . GetElementIDs ( ) )
{
2023-05-09 05:17:49 -04:00
VertIndexAndZ . Emplace ( VertexID . GetValue ( ) , VertexPositions [ VertexID ] ) ;
2020-01-23 16:28:59 -05:00
}
// Sort the vertices by z value
VertIndexAndZ . Sort ( MeshDescriptionOperationNamespace : : FCompareIndexAndZ ( ) ) ;
// Search for duplicates, quickly!
for ( int32 i = 0 ; i < VertIndexAndZ . Num ( ) ; i + + )
{
FVertexID Index_i = FVertexID ( VertIndexAndZ [ i ] . Index ) ;
if ( OutVertexIDRemap . Contains ( Index_i ) )
{
continue ;
}
OutVertexIDRemap . FindOrAdd ( Index_i ) = Index_i ;
// only need to search forward, since we add pairs both ways
for ( int32 j = i + 1 ; j < VertIndexAndZ . Num ( ) ; j + + )
{
if ( FMath : : Abs ( VertIndexAndZ [ j ] . Z - VertIndexAndZ [ i ] . Z ) > WeldingThreshold )
break ; // can't be any more dups
2021-11-18 14:37:34 -05:00
const FVector3f & PositionA = * ( VertIndexAndZ [ i ] . OriginalVector ) ;
const FVector3f & PositionB = * ( VertIndexAndZ [ j ] . OriginalVector ) ;
2020-01-23 16:28:59 -05:00
if ( PositionA . Equals ( PositionB , WeldingThreshold ) )
{
OutVertexIDRemap . FindOrAdd ( FVertexID ( VertIndexAndZ [ j ] . Index ) ) = Index_i ;
}
}
}
}
2020-12-11 14:21:20 -04:00
FSHAHash FStaticMeshOperations : : ComputeSHAHash ( const FMeshDescription & MeshDescription , bool bSkipTransientAttributes )
2020-01-23 16:28:59 -05:00
{
FSHA1 HashState ;
TArray < FName > AttributesNames ;
2020-12-11 14:21:20 -04:00
auto HashAttributeSet = [ & AttributesNames , & HashState , bSkipTransientAttributes ] ( const auto & AttributeSet )
2020-01-23 16:28:59 -05:00
{
AttributesNames . Reset ( ) ;
2020-12-11 14:21:20 -04:00
if ( ! bSkipTransientAttributes )
{
AttributeSet . GetAttributeNames ( AttributesNames ) ;
}
else
{
AttributeSet . ForEach ( [ & AttributesNames ] ( const FName AttributeName , auto AttributesRef )
{
bool bIsTransient = ( AttributesRef . GetFlags ( ) & EMeshAttributeFlags : : Transient ) ! = EMeshAttributeFlags : : None ;
if ( ! bIsTransient )
{
AttributesNames . Add ( AttributeName ) ;
}
} ) ;
}
AttributesNames . Sort ( FNameLexicalLess ( ) ) ;
2020-01-23 16:28:59 -05:00
for ( FName AttributeName : AttributesNames )
{
uint32 AttributeHash = AttributeSet . GetHash ( AttributeName ) ;
HashState . Update ( ( uint8 * ) & AttributeHash , sizeof ( AttributeHash ) ) ;
}
} ;
HashAttributeSet ( MeshDescription . VertexAttributes ( ) ) ;
HashAttributeSet ( MeshDescription . VertexInstanceAttributes ( ) ) ;
HashAttributeSet ( MeshDescription . EdgeAttributes ( ) ) ;
HashAttributeSet ( MeshDescription . PolygonAttributes ( ) ) ;
HashAttributeSet ( MeshDescription . PolygonGroupAttributes ( ) ) ;
FSHAHash OutHash ;
HashState . Final ( ) ;
HashState . GetHash ( & OutHash . Hash [ 0 ] ) ;
return OutHash ;
}
2020-02-17 14:50:55 -05:00
void FStaticMeshOperations : : FlipPolygons ( FMeshDescription & MeshDescription )
{
TSet < FVertexInstanceID > VertexInstanceIDs ;
2022-01-06 16:44:09 +00:00
for ( const FTriangleID TriangleID : MeshDescription . Triangles ( ) . GetElementIDs ( ) )
2020-02-17 14:50:55 -05:00
{
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
TArrayView < const FVertexInstanceID > TriVertInstances = MeshDescription . GetTriangleVertexInstances ( TriangleID ) ;
for ( const FVertexInstanceID TriVertInstance : TriVertInstances )
{
VertexInstanceIDs . Add ( TriVertInstance ) ;
}
MeshDescription . ReverseTriangleFacing ( TriangleID ) ;
2020-02-17 14:50:55 -05:00
}
// Flip tangents and normals
2021-05-05 15:07:25 -04:00
TVertexInstanceAttributesRef < FVector3f > VertexNormals = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector3f > ( MeshAttribute : : VertexInstance : : Normal ) ;
TVertexInstanceAttributesRef < FVector3f > VertexTangents = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector3f > ( MeshAttribute : : VertexInstance : : Tangent ) ;
2020-02-17 14:50:55 -05:00
for ( const FVertexInstanceID VertexInstanceID : VertexInstanceIDs )
{
// Just reverse the sign of the normals/tangents; note that since binormals are the cross product of normal with tangent, they are left untouched
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
VertexNormals [ VertexInstanceID ] * = - 1.0f ;
VertexTangents [ VertexInstanceID ] * = - 1.0f ;
2020-02-17 14:50:55 -05:00
}
}
2023-12-01 12:15:31 -05:00
void FStaticMeshOperations : : ApplyTransform ( FMeshDescription & MeshDescription , const FTransform & Transform , bool bApplyCorrectNormalTransform )
2023-02-24 03:57:37 -05:00
{
2023-12-01 12:15:31 -05:00
ApplyTransform ( MeshDescription , Transform . ToMatrixWithScale ( ) , bApplyCorrectNormalTransform ) ;
2023-02-24 03:57:37 -05:00
}
2023-12-01 12:15:31 -05:00
void FStaticMeshOperations : : ApplyTransform ( FMeshDescription & MeshDescription , const FMatrix & Transform , bool bApplyCorrectNormalTransform )
2021-01-21 16:22:06 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : ApplyTransform )
2021-05-05 15:07:25 -04:00
TVertexAttributesRef < FVector3f > VertexPositions = MeshDescription . VertexAttributes ( ) . GetAttributesRef < FVector3f > ( MeshAttribute : : Vertex : : Position ) ;
TVertexInstanceAttributesRef < FVector3f > VertexInstanceNormals = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector3f > ( MeshAttribute : : VertexInstance : : Normal ) ;
TVertexInstanceAttributesRef < FVector3f > VertexInstanceTangents = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < FVector3f > ( MeshAttribute : : VertexInstance : : Tangent ) ;
2021-01-21 16:22:06 -04:00
TVertexInstanceAttributesRef < float > VertexInstanceBinormalSigns = MeshDescription . VertexInstanceAttributes ( ) . GetAttributesRef < float > ( MeshAttribute : : VertexInstance : : BinormalSign ) ;
for ( const FVertexID VertexID : MeshDescription . Vertices ( ) . GetElementIDs ( ) )
{
2023-02-24 03:57:37 -05:00
VertexPositions [ VertexID ] = FVector4f ( Transform . TransformPosition ( FVector3d ( VertexPositions [ VertexID ] ) ) ) ;
2021-01-21 16:22:06 -04:00
}
2023-02-24 03:57:37 -05:00
const bool bIsMirrored = Transform . Determinant ( ) < 0.f ;
2021-01-21 16:22:06 -04:00
const float MulBy = bIsMirrored ? - 1.f : 1.f ;
2023-12-01 12:15:31 -05:00
FMatrix NormalsTransform , TangentsTransform ;
if ( bApplyCorrectNormalTransform )
{
// Note: Assuming we'll normalize after, transforming by the transpose-adjoint * the sign of the determinant
// is equivalent to transforming by the inverse transpose; ref: TMatrix::TransformByUsingAdjointT
NormalsTransform = Transform . TransposeAdjoint ( ) * ( double ) MulBy ;
// Note: Tangents *do not* transform by the Transform's inverse transpose, just by the Transform
TangentsTransform = Transform ;
}
else // match UE renderer
{
// UE's renderer transforms normals and tangents without scale (as in FTransform::TransformVectorNoScale)
NormalsTransform = Transform ;
NormalsTransform . RemoveScaling ( ) ;
TangentsTransform = NormalsTransform ;
}
2021-01-21 16:22:06 -04:00
for ( const FVertexInstanceID VertexInstanceID : MeshDescription . VertexInstances ( ) . GetElementIDs ( ) )
{
2021-09-22 10:01:48 -04:00
FVector3f Tangent = VertexInstanceTangents [ VertexInstanceID ] ;
FVector3f Normal = VertexInstanceNormals [ VertexInstanceID ] ;
2021-01-21 16:22:06 -04:00
2023-12-01 12:15:31 -05:00
VertexInstanceTangents [ VertexInstanceID ] = ( FVector3f ) FVector ( TangentsTransform . TransformVector ( ( FVector ) Tangent ) . GetSafeNormal ( ) ) ;
VertexInstanceNormals [ VertexInstanceID ] = ( FVector3f ) FVector ( NormalsTransform . TransformVector ( ( FVector ) Normal ) . GetSafeNormal ( ) ) ;
2023-06-01 10:46:45 -04:00
float BinormalSign = VertexInstanceBinormalSigns [ VertexInstanceID ] ;
2021-01-21 16:22:06 -04:00
VertexInstanceBinormalSigns [ VertexInstanceID ] = BinormalSign * MulBy ;
}
if ( bIsMirrored )
{
MeshDescription . ReverseAllPolygonFacing ( ) ;
}
}
2022-12-05 16:24:30 -05:00
namespace UE : : Private
{
class FPrivateVertexInfo
{
public :
FVector3f Position ;
FVector3f Normal ;
FVector3f Tangents [ 2 ] ;
FLinearColor Color ;
FVector2f TexCoords [ MAX_MESH_TEXTURE_COORDS_MD ] ;
void Validate ( )
{
Normal . Normalize ( ) ;
Tangents [ 0 ] - = ( Tangents [ 0 ] | Normal ) * Normal ;
Tangents [ 0 ] . Normalize ( ) ;
Tangents [ 1 ] - = ( Tangents [ 1 ] | Normal ) * Normal ;
Tangents [ 1 ] - = ( Tangents [ 1 ] | Tangents [ 0 ] ) * Tangents [ 0 ] ;
Tangents [ 1 ] . Normalize ( ) ;
Color = Color . GetClamped ( ) ;
}
bool Equals ( const FPrivateVertexInfo & Other ) const
{
constexpr float UVEpsilon = 1.0f / 1024.0f ;
if ( ! Position . Equals ( Other . Position , UE_THRESH_POINTS_ARE_SAME ) | |
! Tangents [ 0 ] . Equals ( Other . Tangents [ 0 ] , UE_THRESH_NORMALS_ARE_SAME ) | |
! Tangents [ 1 ] . Equals ( Other . Tangents [ 1 ] , UE_THRESH_NORMALS_ARE_SAME ) | |
! Normal . Equals ( Other . Normal , UE_THRESH_NORMALS_ARE_SAME ) | |
! Color . Equals ( Other . Color ) )
{
return false ;
}
// UVs
for ( int32 UVIndex = 0 ; UVIndex < MAX_MESH_TEXTURE_COORDS_MD ; UVIndex + + )
{
if ( ! TexCoords [ UVIndex ] . Equals ( Other . TexCoords [ UVIndex ] , UVEpsilon ) )
{
return false ;
}
}
return true ;
}
} ;
}
int32 FStaticMeshOperations : : GetUniqueVertexCount ( const FMeshDescription & MeshDescription )
{
FOverlappingCorners OverlappingCorners ;
FStaticMeshOperations : : FindOverlappingCorners ( OverlappingCorners , MeshDescription , UE_THRESH_POINTS_ARE_SAME ) ;
2022-12-13 18:17:40 -05:00
return GetUniqueVertexCount ( MeshDescription , OverlappingCorners ) ;
}
int32 FStaticMeshOperations : : GetUniqueVertexCount ( const FMeshDescription & MeshDescription , const FOverlappingCorners & OverlappingCorners )
{
2023-01-23 08:43:42 -05:00
TRACE_CPUPROFILER_EVENT_SCOPE ( FStaticMeshOperations : : GetUniqueVertexCount ) ;
2022-12-13 18:17:40 -05:00
constexpr uint32 NumTexCoords = MAX_MESH_TEXTURE_COORDS_MD ;
2022-12-05 16:24:30 -05:00
TArray < UE : : Private : : FPrivateVertexInfo > Verts ;
Verts . Reserve ( MeshDescription . Vertices ( ) . Num ( ) ) ;
TMap < int32 , int32 > VertsMap ;
int32 NumFaces = MeshDescription . Triangles ( ) . Num ( ) ;
int32 NumWedges = NumFaces * 3 ;
const FStaticMeshConstAttributes MeshAttribute ( MeshDescription ) ;
TVertexAttributesConstRef < FVector3f > VertexPositions = MeshAttribute . GetVertexPositions ( ) ;
TVertexInstanceAttributesConstRef < FVector3f > VertexNormals = MeshAttribute . GetVertexInstanceNormals ( ) ;
TVertexInstanceAttributesConstRef < FVector3f > VertexTangents = MeshAttribute . GetVertexInstanceTangents ( ) ;
TVertexInstanceAttributesConstRef < float > VertexBinormalSigns = MeshAttribute . GetVertexInstanceBinormalSigns ( ) ;
TVertexInstanceAttributesConstRef < FVector4f > VertexColors = MeshAttribute . GetVertexInstanceColors ( ) ;
TVertexInstanceAttributesConstRef < FVector2f > VertexUVs = MeshAttribute . GetVertexInstanceUVs ( ) ;
int32 WedgeIndex = 0 ;
for ( const FTriangleID TriangleID : MeshDescription . Triangles ( ) . GetElementIDs ( ) )
{
TArrayView < const FVertexID > VertexIDs = MeshDescription . GetTriangleVertices ( TriangleID ) ;
FVector3f CornerPositions [ 3 ] ;
for ( int32 TriVert = 0 ; TriVert < 3 ; + + TriVert )
{
const FVertexID VertexID = VertexIDs [ TriVert ] ;
CornerPositions [ TriVert ] = VertexPositions [ VertexID ] ;
}
// Don't process degenerate triangles.
if ( CornerPositions [ 0 ] . Equals ( CornerPositions [ 1 ] , UE_THRESH_POINTS_ARE_SAME ) | |
CornerPositions [ 0 ] . Equals ( CornerPositions [ 2 ] , UE_THRESH_POINTS_ARE_SAME ) | |
CornerPositions [ 1 ] . Equals ( CornerPositions [ 2 ] , UE_THRESH_POINTS_ARE_SAME ) )
{
WedgeIndex + = 3 ;
continue ;
}
for ( int32 TriVert = 0 ; TriVert < 3 ; + + TriVert , + + WedgeIndex )
{
const FVertexInstanceID VertexInstanceID = MeshDescription . GetTriangleVertexInstance ( TriangleID , TriVert ) ;
const FVector3f & VertexPosition = CornerPositions [ TriVert ] ;
UE : : Private : : FPrivateVertexInfo NewVert ;
NewVert . Position = CornerPositions [ TriVert ] ;
NewVert . Tangents [ 0 ] = VertexTangents [ VertexInstanceID ] ;
NewVert . Normal = VertexNormals [ VertexInstanceID ] ;
NewVert . Tangents [ 1 ] = FVector3f ( 0.0f ) ;
if ( ! NewVert . Normal . IsNearlyZero ( SMALL_NUMBER ) & & ! NewVert . Tangents [ 0 ] . IsNearlyZero ( SMALL_NUMBER ) )
{
NewVert . Tangents [ 1 ] = FVector3f : : CrossProduct ( NewVert . Normal , NewVert . Tangents [ 0 ] ) . GetSafeNormal ( ) * VertexBinormalSigns [ VertexInstanceID ] ;
}
// Fix bad tangents
NewVert . Tangents [ 0 ] = NewVert . Tangents [ 0 ] . ContainsNaN ( ) ? FVector3f : : ZeroVector : NewVert . Tangents [ 0 ] ;
NewVert . Tangents [ 1 ] = NewVert . Tangents [ 1 ] . ContainsNaN ( ) ? FVector3f : : ZeroVector : NewVert . Tangents [ 1 ] ;
NewVert . Normal = NewVert . Normal . ContainsNaN ( ) ? FVector3f : : ZeroVector : NewVert . Normal ;
NewVert . Color = FLinearColor ( VertexColors [ VertexInstanceID ] ) ;
for ( int32 UVIndex = 0 ; UVIndex < NumTexCoords ; UVIndex + + )
{
if ( UVIndex < VertexUVs . GetNumChannels ( ) )
{
NewVert . TexCoords [ UVIndex ] = VertexUVs . Get ( VertexInstanceID , UVIndex ) ;
}
else
{
NewVert . TexCoords [ UVIndex ] = FVector2f : : ZeroVector ;
}
}
// Make sure this vertex is valid from the start
NewVert . Validate ( ) ;
//Never add duplicated vertex instance
//Use WedgeIndex since OverlappingCorners has been built based on that
const TArray < int32 > & DupVerts = OverlappingCorners . FindIfOverlapping ( WedgeIndex ) ;
int32 Index = INDEX_NONE ;
for ( int32 k = 0 ; k < DupVerts . Num ( ) ; k + + )
{
if ( DupVerts [ k ] > = WedgeIndex )
{
// the verts beyond me haven't been placed yet, so these duplicates are not relevant
break ;
}
int32 * Location = VertsMap . Find ( DupVerts [ k ] ) ;
if ( Location )
{
UE : : Private : : FPrivateVertexInfo & FoundVert = Verts [ * Location ] ;
if ( NewVert . Equals ( FoundVert ) )
{
Index = * Location ;
break ;
}
}
}
if ( Index = = INDEX_NONE )
{
Index = Verts . Add ( NewVert ) ;
VertsMap . Add ( WedgeIndex , Index ) ;
}
}
}
return Verts . Num ( ) ;
}
2023-03-31 15:18:03 -04:00
void FStaticMeshOperations : : ReorderMeshDescriptionPolygonGroups ( const FMeshDescription & SourceMeshDescription
, FMeshDescription & DestinationMeshDescription
, TOptional < const FString > DestinationUnmatchMaterialName_Msg
2023-05-15 12:50:52 -04:00
, TOptional < const FString > DestinationPolygonGroupCountDifferFromSource_Msg )
2023-03-31 15:18:03 -04:00
{
if ( SourceMeshDescription . IsEmpty ( ) | | DestinationMeshDescription . IsEmpty ( ) | | DestinationMeshDescription . PolygonGroups ( ) . Num ( ) < = 1 )
{
//Nothing to re-order
return ;
}
2023-05-15 12:50:52 -04:00
//Do not allow reorder if the material count is different between the destination and the source
if ( DestinationMeshDescription . PolygonGroups ( ) . Num ( ) ! = SourceMeshDescription . PolygonGroups ( ) . Num ( ) )
{
if ( DestinationPolygonGroupCountDifferFromSource_Msg . IsSet ( ) )
{
UE_LOG ( LogStaticMeshOperations , Warning , TEXT ( " %s " ) , * DestinationPolygonGroupCountDifferFromSource_Msg . GetValue ( ) ) ;
}
return ;
}
2023-03-31 15:18:03 -04:00
FStaticMeshConstAttributes SourceAttribute ( SourceMeshDescription ) ;
TPolygonGroupAttributesConstRef < FName > SourceMaterialSlotNameAttribute = SourceAttribute . GetPolygonGroupMaterialSlotNames ( ) ;
FStaticMeshAttributes DestinationAttribute ( DestinationMeshDescription ) ;
TPolygonGroupAttributesConstRef < FName > DestinationMaterialSlotNameAttribute = DestinationAttribute . GetPolygonGroupMaterialSlotNames ( ) ;
TMap < FPolygonGroupID , FPolygonGroupID > MatchPolygonGroupsDestSource ;
2023-05-15 12:50:52 -04:00
TMap < FPolygonGroupID , bool > SourceMaterialMatched ;
SourceMaterialMatched . Reserve ( SourceMaterialSlotNameAttribute . GetNumElements ( ) ) ;
2023-03-31 15:18:03 -04:00
for ( FPolygonGroupID SourcePolygonGroupID : SourceMeshDescription . PolygonGroups ( ) . GetElementIDs ( ) )
{
2023-05-15 12:50:52 -04:00
SourceMaterialMatched . Add ( SourcePolygonGroupID , false ) ;
2023-03-31 15:18:03 -04:00
}
2023-05-15 12:50:52 -04:00
TMap < FPolygonGroupID , bool > DestinationMaterialMatched ;
DestinationMaterialMatched . Reserve ( DestinationMaterialSlotNameAttribute . GetNumElements ( ) ) ;
2023-03-31 15:18:03 -04:00
for ( FPolygonGroupID DestinationPolygonGroupID : DestinationMeshDescription . PolygonGroups ( ) . GetElementIDs ( ) )
{
2023-05-15 12:50:52 -04:00
DestinationMaterialMatched . Add ( DestinationPolygonGroupID , false ) ;
}
//Find the material name match
for ( TPair < FPolygonGroupID , bool > & DestinationMatched : DestinationMaterialMatched )
{
const FName MaterialNameToMatch = DestinationMaterialSlotNameAttribute [ DestinationMatched . Key ] ;
2023-03-31 15:18:03 -04:00
FPolygonGroupID MatchPolygonGroupID = INDEX_NONE ;
2023-05-15 12:50:52 -04:00
for ( TPair < FPolygonGroupID , bool > & SourceMatched : SourceMaterialMatched )
2023-03-31 15:18:03 -04:00
{
2023-05-15 12:50:52 -04:00
if ( SourceMatched . Value )
2023-03-31 15:18:03 -04:00
{
2023-05-15 12:50:52 -04:00
continue ;
}
if ( SourceMaterialSlotNameAttribute [ SourceMatched . Key ] = = MaterialNameToMatch )
{
MatchPolygonGroupID = SourceMatched . Key ;
SourceMatched . Value = true ;
DestinationMatched . Value = true ;
break ;
2023-03-31 15:18:03 -04:00
}
}
if ( MatchPolygonGroupID ! = INDEX_NONE )
{
2023-05-15 12:50:52 -04:00
MatchPolygonGroupsDestSource . FindOrAdd ( DestinationMatched . Key ) = MatchPolygonGroupID ;
2023-03-31 15:18:03 -04:00
}
}
2023-05-15 12:50:52 -04:00
if ( MatchPolygonGroupsDestSource . Num ( ) < DestinationMaterialMatched . Num ( ) & & DestinationUnmatchMaterialName_Msg . IsSet ( ) )
2023-03-31 15:18:03 -04:00
{
2023-05-15 12:50:52 -04:00
UE_LOG ( LogStaticMeshOperations , Warning , TEXT ( " %s " ) , * DestinationUnmatchMaterialName_Msg . GetValue ( ) ) ;
}
//Iterate the unmatched destination and use the first unmatched source
for ( TPair < FPolygonGroupID , bool > & DestinationMatched : DestinationMaterialMatched )
{
if ( DestinationMatched . Value )
2023-03-31 15:18:03 -04:00
{
2023-05-15 12:50:52 -04:00
//Skip this destination because its already matched
continue ;
}
//Match the first unmatched source we found
for ( TPair < FPolygonGroupID , bool > & SourceMatched : SourceMaterialMatched )
{
if ( SourceMatched . Value )
2023-03-31 15:18:03 -04:00
{
2023-05-15 12:50:52 -04:00
//Skip this source because its already matched
continue ;
2023-03-31 15:18:03 -04:00
}
2023-05-15 12:50:52 -04:00
//Force match
MatchPolygonGroupsDestSource . FindOrAdd ( DestinationMatched . Key ) = SourceMatched . Key ;
DestinationMatched . Value = true ;
SourceMatched . Value = true ;
break ;
2023-03-31 15:18:03 -04:00
}
}
2023-05-15 12:50:52 -04:00
//Since both source and destination have the same amount of material, the MatchPolygonGroupsDestSource should have the same count.
if ( ensure ( MatchPolygonGroupsDestSource . Num ( ) = = DestinationMaterialMatched . Num ( ) ) )
2023-03-31 15:18:03 -04:00
{
2023-05-15 12:50:52 -04:00
//Remap the polygon group with the correct ID
DestinationMeshDescription . RemapPolygonGroups ( MatchPolygonGroupsDestSource ) ;
2023-03-31 15:18:03 -04:00
}
}
2023-11-01 09:26:52 -04:00
bool FStaticMeshOperations : : ValidateAndFixData ( FMeshDescription & MeshDescription , const FString & DebugName )
{
bool bHasInvalidPositions = false ;
bool bHasInvalidTangentSpaces = false ;
bool bHasInvalidUVs = false ;
bool bHasInvalidVertexColors = false ;
FStaticMeshAttributes Attributes ( MeshDescription ) ;
TVertexAttributesRef < FVector3f > VertexPositions = Attributes . GetVertexPositions ( ) ;
for ( const FVertexID VertexID : MeshDescription . Vertices ( ) . GetElementIDs ( ) )
{
if ( VertexPositions [ VertexID ] . ContainsNaN ( ) )
{
bHasInvalidPositions = true ;
VertexPositions [ VertexID ] = FVector3f : : ZeroVector ;
}
}
TVertexInstanceAttributesRef < FVector3f > VertexInstanceNormals = Attributes . GetVertexInstanceNormals ( ) ;
TVertexInstanceAttributesRef < FVector3f > VertexInstanceTangents = Attributes . GetVertexInstanceTangents ( ) ;
TVertexInstanceAttributesRef < float > VertexInstanceBinormalSigns = Attributes . GetVertexInstanceBinormalSigns ( ) ;
TVertexInstanceAttributesRef < FVector2f > VertexInstanceUVs = Attributes . GetVertexInstanceUVs ( ) ;
TVertexInstanceAttributesRef < FVector4f > VertexInstanceColors = Attributes . GetVertexInstanceColors ( ) ;
2024-03-04 21:06:34 -05:00
const int32 NumUVs = VertexInstanceUVs . GetNumChannels ( ) ;
2023-11-01 09:26:52 -04:00
for ( const FVertexInstanceID VertexInstanceID : MeshDescription . VertexInstances ( ) . GetElementIDs ( ) )
{
if ( VertexInstanceNormals [ VertexInstanceID ] . ContainsNaN ( ) )
{
bHasInvalidTangentSpaces = true ;
VertexInstanceNormals [ VertexInstanceID ] = FVector3f : : Zero ( ) ;
}
if ( VertexInstanceTangents [ VertexInstanceID ] . ContainsNaN ( ) )
{
bHasInvalidTangentSpaces = true ;
VertexInstanceTangents [ VertexInstanceID ] = FVector3f : : Zero ( ) ;
}
if ( FMath : : IsNaN ( VertexInstanceBinormalSigns [ VertexInstanceID ] ) )
{
bHasInvalidTangentSpaces = true ;
VertexInstanceBinormalSigns [ VertexInstanceID ] = 0.0f ;
}
2024-03-04 21:06:34 -05:00
for ( int32 UVIndex = 0 ; UVIndex < NumUVs ; UVIndex + + )
2023-11-01 09:26:52 -04:00
{
2024-03-04 21:06:34 -05:00
if ( VertexInstanceUVs . Get ( VertexInstanceID , UVIndex ) . ContainsNaN ( ) )
{
bHasInvalidUVs = true ;
VertexInstanceUVs . Set ( VertexInstanceID , UVIndex , FVector2f : : Zero ( ) ) ;
}
2023-11-01 09:26:52 -04:00
}
if ( VertexInstanceColors [ VertexInstanceID ] . ContainsNaN ( ) )
{
bHasInvalidVertexColors = true ;
VertexInstanceColors [ VertexInstanceID ] = FVector4f : : One ( ) ;
}
}
2024-03-04 21:06:34 -05:00
if ( ! DebugName . IsEmpty ( ) )
2023-11-01 09:26:52 -04:00
{
2024-03-04 21:06:34 -05:00
if ( bHasInvalidPositions )
{
UE_LOG ( LogStaticMeshOperations , Display , TEXT ( " Mesh %s has NaNs in it's vertex positions! Offending positions are set to zero. " ) , * DebugName ) ;
}
if ( bHasInvalidTangentSpaces )
{
UE_LOG ( LogStaticMeshOperations , Display , TEXT ( " Mesh %s has NaNs in it's vertex instance tangent space! Offending tangents are set to zero. " ) , * DebugName ) ;
}
if ( bHasInvalidUVs )
{
UE_LOG ( LogStaticMeshOperations , Display , TEXT ( " Mesh %s has NaNs in it's vertex instance uvs! Offending uvs are set to zero. " ) , * DebugName ) ;
}
if ( bHasInvalidVertexColors )
{
UE_LOG ( LogStaticMeshOperations , Display , TEXT ( " Mesh %s has NaNs in it's vertex instance colors! Offending colors are set to white. " ) , * DebugName ) ;
}
2023-11-01 09:26:52 -04:00
}
return ! bHasInvalidPositions & & ! bHasInvalidTangentSpaces & & ! bHasInvalidUVs & & ! bHasInvalidVertexColors ;
}
2021-01-21 16:22:06 -04:00
# undef LOCTEXT_NAMESPACE