2019-12-26 23:06:02 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
# include "StaticMesh.h"
2014-03-14 14:13:41 -04:00
# include "Importer.h"
namespace Lightmass
{
/**
* Functions used for transforming a static mesh component based on a spline .
* This needs to be updated if the spline functionality changes !
*/
static float SmoothStep ( float A , float B , float X )
{
if ( X < A )
{
return 0.0f ;
}
else if ( X > = B )
{
return 1.0f ;
}
const float InterpFraction = ( X - A ) / ( B - A ) ;
return InterpFraction * InterpFraction * ( 3.0f - 2.0f * InterpFraction ) ;
}
2021-11-22 22:06:39 -05:00
static FVector3f SplineEvalPos ( const FVector3f & StartPos , const FVector3f & StartTangent , const FVector3f & EndPos , const FVector3f & EndTangent , float A )
2014-03-14 14:13:41 -04:00
{
const float A2 = A * A ;
const float A3 = A2 * A ;
return ( ( ( 2 * A3 ) - ( 3 * A2 ) + 1 ) * StartPos ) + ( ( A3 - ( 2 * A2 ) + A ) * StartTangent ) + ( ( A3 - A2 ) * EndTangent ) + ( ( ( - 2 * A3 ) + ( 3 * A2 ) ) * EndPos ) ;
}
2021-11-22 22:06:39 -05:00
static FVector3f SplineEvalDir ( const FVector3f & StartPos , const FVector3f & StartTangent , const FVector3f & EndPos , const FVector3f & EndTangent , float A )
2014-03-14 14:13:41 -04:00
{
2021-11-22 22:06:39 -05:00
const FVector3f C = ( 6 * StartPos ) + ( 3 * StartTangent ) + ( 3 * EndTangent ) - ( 6 * EndPos ) ;
const FVector3f D = ( - 6 * StartPos ) - ( 4 * StartTangent ) - ( 2 * EndTangent ) + ( 6 * EndPos ) ;
const FVector3f E = StartTangent ;
2014-03-14 14:13:41 -04:00
const float A2 = A * A ;
2014-11-26 10:01:12 -05:00
return ( ( C * A2 ) + ( D * A ) + E ) . GetSafeNormal ( ) ;
2014-03-14 14:13:41 -04:00
}
/** Calculate full transform that defines frame along spline, given the Z of a vertex. */
/** Note: This is mirrored from USplineMeshComponent::CalcSliceTransform() and LocalVertexShader.usf. If you update one of these, please update them all! */
2021-11-22 22:06:39 -05:00
static FMatrix44f CalcSliceTransform ( float ZPos , const FSplineMeshParams & SplineParams )
2014-03-14 14:13:41 -04:00
{
// Find how far 'along' mesh we are
const float Alpha = ( ZPos - SplineParams . MeshMinZ ) / SplineParams . MeshRangeZ ;
// Apply hermite interp to Alpha if desired
const float HermiteAlpha = SplineParams . bSmoothInterpRollScale ? SmoothStep ( 0.0 , 1.0 , Alpha ) : Alpha ;
// Then find the point and direction of the spline at this point along
2021-11-22 22:06:39 -05:00
FVector3f SplinePos = SplineEvalPos ( SplineParams . StartPos , SplineParams . StartTangent , SplineParams . EndPos , SplineParams . EndTangent , Alpha ) ;
const FVector3f SplineDir = SplineEvalDir ( SplineParams . StartPos , SplineParams . StartTangent , SplineParams . EndPos , SplineParams . EndTangent , Alpha ) ;
2014-03-14 14:13:41 -04:00
// Find base frenet frame
2021-11-22 22:06:39 -05:00
const FVector3f BaseXVec = ( SplineParams . SplineUpDir ^ SplineDir ) . GetSafeNormal ( ) ;
const FVector3f BaseYVec = ( SplineDir ^ BaseXVec ) . GetSafeNormal ( ) ;
2014-03-14 14:13:41 -04:00
// Offset the spline by the desired amount
2021-11-22 22:06:39 -05:00
const FVector2f SliceOffset = FMath : : Lerp < FVector2f > ( SplineParams . StartOffset , SplineParams . EndOffset , HermiteAlpha ) ;
2014-03-14 14:13:41 -04:00
SplinePos + = SliceOffset . X * BaseXVec ;
SplinePos + = SliceOffset . Y * BaseYVec ;
// Apply roll to frame around spline
const float UseRoll = FMath : : Lerp ( SplineParams . StartRoll , SplineParams . EndRoll , HermiteAlpha ) ;
const float CosAng = FMath : : Cos ( UseRoll ) ;
const float SinAng = FMath : : Sin ( UseRoll ) ;
2021-11-22 22:06:39 -05:00
const FVector3f XVec = ( CosAng * BaseXVec ) - ( SinAng * BaseYVec ) ;
const FVector3f YVec = ( CosAng * BaseYVec ) + ( SinAng * BaseXVec ) ;
2014-03-14 14:13:41 -04:00
// Find scale at this point along spline
2021-11-22 22:06:39 -05:00
const FVector2f UseScale = FMath : : Lerp ( SplineParams . StartScale , SplineParams . EndScale , HermiteAlpha ) ;
2014-03-14 14:13:41 -04:00
// Build overall transform
2021-11-22 22:06:39 -05:00
FMatrix44f SliceTransform ;
2014-03-14 14:13:41 -04:00
switch ( SplineParams . ForwardAxis )
{
case ESplineMeshAxis : : X :
2021-11-22 22:06:39 -05:00
SliceTransform = FMatrix44f ( SplineDir , UseScale . X * XVec , UseScale . Y * YVec , SplinePos ) ;
2014-03-14 14:13:41 -04:00
break ;
case ESplineMeshAxis : : Y :
2021-11-22 22:06:39 -05:00
SliceTransform = FMatrix44f ( UseScale . Y * YVec , SplineDir , UseScale . X * XVec , SplinePos ) ;
2014-03-14 14:13:41 -04:00
break ;
case ESplineMeshAxis : : Z :
2021-11-22 22:06:39 -05:00
SliceTransform = FMatrix44f ( UseScale . X * XVec , UseScale . Y * YVec , SplineDir , SplinePos ) ;
2014-03-14 14:13:41 -04:00
break ;
default :
check ( 0 ) ;
break ;
}
return SliceTransform ;
}
/** Calculate rotation matrix that defines frame along spline, given the Z of a vertex. */
2021-11-22 22:06:39 -05:00
static FMatrix44f CalcSliceRot ( float ZPos , const FSplineMeshParams & SplineParams )
2014-03-14 14:13:41 -04:00
{
// Find how far 'along' mesh we are
const float Alpha = ( ZPos - SplineParams . MeshMinZ ) / SplineParams . MeshRangeZ ;
// Apply hermite interp to Alpha if desired
const float HermiteAlpha = SplineParams . bSmoothInterpRollScale ? SmoothStep ( 0.0 , 1.0 , Alpha ) : Alpha ;
// Then find the point and direction of the spline at this point along
2021-11-22 22:06:39 -05:00
const FVector3f SplineDir = SplineEvalDir ( SplineParams . StartPos , SplineParams . StartTangent , SplineParams . EndPos , SplineParams . EndTangent , Alpha ) ;
2014-03-14 14:13:41 -04:00
// Find base frenet frame
2021-11-22 22:06:39 -05:00
const FVector3f BaseXVec = ( SplineParams . SplineUpDir ^ SplineDir ) . GetSafeNormal ( ) ;
const FVector3f BaseYVec = ( SplineDir ^ BaseXVec ) . GetSafeNormal ( ) ;
2014-03-14 14:13:41 -04:00
// Apply roll to frame around spline
const float UseRoll = FMath : : Lerp ( SplineParams . StartRoll , SplineParams . EndRoll , HermiteAlpha ) ;
const float CosAng = FMath : : Cos ( UseRoll ) ;
const float SinAng = FMath : : Sin ( UseRoll ) ;
2021-11-22 22:06:39 -05:00
const FVector3f XVec = ( CosAng * BaseXVec ) - ( SinAng * BaseYVec ) ;
const FVector3f YVec = ( CosAng * BaseYVec ) + ( SinAng * BaseXVec ) ;
2014-03-14 14:13:41 -04:00
// Build rotation transform
2021-11-22 22:06:39 -05:00
FMatrix44f SliceTransform ;
2014-03-14 14:13:41 -04:00
switch ( SplineParams . ForwardAxis )
{
case ESplineMeshAxis : : X :
2021-11-22 22:06:39 -05:00
SliceTransform = FMatrix44f ( SplineDir , XVec , YVec , FVector3f ( 0 , 0 , 0 ) ) ;
2014-03-14 14:13:41 -04:00
break ;
case ESplineMeshAxis : : Y :
2021-11-22 22:06:39 -05:00
SliceTransform = FMatrix44f ( YVec , SplineDir , XVec , FVector3f ( 0 , 0 , 0 ) ) ;
2014-03-14 14:13:41 -04:00
break ;
case ESplineMeshAxis : : Z :
2021-11-22 22:06:39 -05:00
SliceTransform = FMatrix44f ( XVec , YVec , SplineDir , FVector3f ( 0 , 0 , 0 ) ) ;
2014-03-14 14:13:41 -04:00
break ;
default :
check ( 0 ) ;
break ;
}
return SliceTransform ;
}
/**
* Creates a static lighting vertex to represent the given static mesh vertex .
* @ param VertexBuffer - The static mesh ' s vertex buffer .
* @ param VertexIndex - The index of the static mesh vertex to access .
* @ param OutVertex - Upon return , contains a static lighting vertex representing the specified static mesh vertex .
*/
static void GetStaticLightingVertex (
const FStaticMeshVertex & InVertex ,
2021-11-22 22:06:39 -05:00
const FMatrix44f & LocalToWorld ,
const FMatrix44f & LocalToWorldInverseTranspose ,
2014-03-14 14:13:41 -04:00
bool bIsSplineMesh ,
const FSplineMeshParams & SplineParams ,
FStaticLightingVertex & OutVertex
)
{
if ( bIsSplineMesh )
{
// Make transform for this point along spline
2021-11-22 22:06:39 -05:00
const FMatrix44f SliceTransform = CalcSliceTransform ( InVertex . Position [ SplineParams . ForwardAxis ] , SplineParams ) ;
2014-03-14 14:13:41 -04:00
// Remove Z (transform will move us along spline)
2021-11-22 22:06:39 -05:00
FVector4f SlicePos = InVertex . Position ;
2014-03-14 14:13:41 -04:00
SlicePos [ SplineParams . ForwardAxis ] = 0 ;
// Transform into mesh space
2021-11-22 22:06:39 -05:00
const FVector4f LocalPos = SliceTransform . TransformPosition ( SlicePos ) ;
2014-03-14 14:13:41 -04:00
// Transform from mesh to world space
OutVertex . WorldPosition = LocalToWorld . TransformPosition ( LocalPos ) ;
2021-11-22 22:06:39 -05:00
const FMatrix44f SliceRot = CalcSliceRot ( InVertex . Position [ SplineParams . ForwardAxis ] , SplineParams ) ;
2014-03-14 14:13:41 -04:00
2021-11-22 22:06:39 -05:00
const FVector4f LocalSpaceTangentX = SliceRot . TransformVector ( InVertex . TangentX ) ;
const FVector4f LocalSpaceTangentY = SliceRot . TransformVector ( InVertex . TangentY ) ;
const FVector4f LocalSpaceTangentZ = SliceRot . TransformVector ( InVertex . TangentZ ) ;
2014-03-14 14:13:41 -04:00
2014-11-26 10:01:12 -05:00
OutVertex . WorldTangentX = LocalToWorld . TransformVector ( LocalSpaceTangentX ) . GetSafeNormal ( ) ;
OutVertex . WorldTangentY = LocalToWorld . TransformVector ( LocalSpaceTangentY ) . GetSafeNormal ( ) ;
OutVertex . WorldTangentZ = LocalToWorldInverseTranspose . TransformVector ( LocalSpaceTangentZ ) . GetSafeNormal ( ) ;
2014-03-14 14:13:41 -04:00
}
else
{
OutVertex . WorldPosition = LocalToWorld . TransformPosition ( InVertex . Position ) ;
2014-11-26 10:01:12 -05:00
OutVertex . WorldTangentX = LocalToWorld . TransformVector ( InVertex . TangentX ) . GetSafeNormal ( ) ;
OutVertex . WorldTangentY = LocalToWorld . TransformVector ( InVertex . TangentY ) . GetSafeNormal ( ) ;
OutVertex . WorldTangentZ = LocalToWorldInverseTranspose . TransformVector ( InVertex . TangentZ ) . GetSafeNormal ( ) ;
2014-03-14 14:13:41 -04:00
}
// WorldTangentZ can end up a 0 vector if it was small to begin with and LocalToWorld contains large scale factors.
if ( ! OutVertex . WorldTangentZ . IsUnit3 ( ) )
{
2014-11-26 10:01:12 -05:00
OutVertex . WorldTangentZ = ( OutVertex . WorldTangentX ^ OutVertex . WorldTangentY ) . GetSafeNormal ( ) ;
2014-03-14 14:13:41 -04:00
}
2019-09-28 08:19:35 -04:00
for ( uint32 LightmapTextureCoordinateIndex = 0 ; LightmapTextureCoordinateIndex < UE_ARRAY_COUNT ( InVertex . UVs ) ; LightmapTextureCoordinateIndex + + )
2014-03-14 14:13:41 -04:00
{
OutVertex . TextureCoordinates [ LightmapTextureCoordinateIndex ] = InVertex . UVs [ LightmapTextureCoordinateIndex ] ;
}
}
// FStaticLightingMesh interface.
void FStaticMeshStaticLightingMesh : : GetTriangle ( int32 TriangleIndex , FStaticLightingVertex & OutV0 , FStaticLightingVertex & OutV1 , FStaticLightingVertex & OutV2 , int32 & ElementIndex ) const
{
const FStaticMeshLOD & LODRenderData = StaticMesh - > GetLOD ( GetMeshLODIndex ( ) ) ;
// Lookup the triangle's vertex indices.
const uint32 I0 = LODRenderData . GetIndex ( TriangleIndex * 3 + 0 ) ;
const uint32 I1 = LODRenderData . GetIndex ( TriangleIndex * 3 + ( bReverseWinding ? 2 : 1 ) ) ;
const uint32 I2 = LODRenderData . GetIndex ( TriangleIndex * 3 + ( bReverseWinding ? 1 : 2 ) ) ;
// Translate the triangle's static mesh vertices to static lighting vertices.
GetStaticLightingVertex ( LODRenderData . GetVertex ( I0 ) , LocalToWorld , LocalToWorldInverseTranspose , bIsSplineMesh , SplineParameters , OutV0 ) ;
GetStaticLightingVertex ( LODRenderData . GetVertex ( I1 ) , LocalToWorld , LocalToWorldInverseTranspose , bIsSplineMesh , SplineParameters , OutV1 ) ;
GetStaticLightingVertex ( LODRenderData . GetVertex ( I2 ) , LocalToWorld , LocalToWorldInverseTranspose , bIsSplineMesh , SplineParameters , OutV2 ) ;
const FStaticMeshLOD & MeshLOD = StaticMesh - > GetLOD ( GetMeshLODIndex ( ) ) ;
ElementIndex = INDEX_NONE ;
for ( uint32 MeshElementIndex = 0 ; MeshElementIndex < MeshLOD . NumElements ; MeshElementIndex + + )
{
const FStaticMeshElement & CurrentElement = MeshLOD . GetElement ( MeshElementIndex ) ;
if ( ( uint32 ) TriangleIndex > = CurrentElement . FirstIndex / 3 & & ( uint32 ) TriangleIndex < CurrentElement . FirstIndex / 3 + CurrentElement . NumTriangles )
{
ElementIndex = MeshElementIndex ;
break ;
}
}
check ( ElementIndex > = 0 ) ;
}
2019-09-14 09:45:25 -04:00
void FStaticMeshStaticLightingMesh : : GetNonTransformedTriangle ( int32 TriangleIndex , FStaticLightingVertex & OutV0 , FStaticLightingVertex & OutV1 , FStaticLightingVertex & OutV2 , int32 & ElementIndex ) const
{
check ( ! bIsSplineMesh ) ;
const FStaticMeshLOD & LODRenderData = StaticMesh - > GetLOD ( GetMeshLODIndex ( ) ) ;
// Lookup the triangle's vertex indices.
const uint32 I0 = LODRenderData . GetIndex ( TriangleIndex * 3 + 0 ) ;
const uint32 I1 = LODRenderData . GetIndex ( TriangleIndex * 3 + 1 ) ;
const uint32 I2 = LODRenderData . GetIndex ( TriangleIndex * 3 + 2 ) ;
// Translate the triangle's static mesh vertices to static lighting vertices.
2021-11-22 22:06:39 -05:00
GetStaticLightingVertex ( LODRenderData . GetVertex ( I0 ) , FMatrix44f : : Identity , FMatrix44f : : Identity , false , SplineParameters , OutV0 ) ;
GetStaticLightingVertex ( LODRenderData . GetVertex ( I1 ) , FMatrix44f : : Identity , FMatrix44f : : Identity , false , SplineParameters , OutV1 ) ;
GetStaticLightingVertex ( LODRenderData . GetVertex ( I2 ) , FMatrix44f : : Identity , FMatrix44f : : Identity , false , SplineParameters , OutV2 ) ;
2019-09-14 09:45:25 -04:00
const FStaticMeshLOD & MeshLOD = StaticMesh - > GetLOD ( GetMeshLODIndex ( ) ) ;
ElementIndex = INDEX_NONE ;
for ( uint32 MeshElementIndex = 0 ; MeshElementIndex < MeshLOD . NumElements ; MeshElementIndex + + )
{
const FStaticMeshElement & CurrentElement = MeshLOD . GetElement ( MeshElementIndex ) ;
if ( ( uint32 ) TriangleIndex > = CurrentElement . FirstIndex / 3 & & ( uint32 ) TriangleIndex < CurrentElement . FirstIndex / 3 + CurrentElement . NumTriangles )
{
ElementIndex = MeshElementIndex ;
break ;
}
}
check ( ElementIndex > = 0 ) ;
}
2014-03-14 14:13:41 -04:00
void FStaticMeshStaticLightingMesh : : GetTriangleIndices ( int32 TriangleIndex , int32 & OutI0 , int32 & OutI1 , int32 & OutI2 ) const
{
const FStaticMeshLOD & LODRenderData = StaticMesh - > GetLOD ( GetMeshLODIndex ( ) ) ;
// Lookup the triangle's vertex indices.
OutI0 = LODRenderData . GetIndex ( TriangleIndex * 3 + 0 ) ;
OutI1 = LODRenderData . GetIndex ( TriangleIndex * 3 + ( bReverseWinding ? 2 : 1 ) ) ;
OutI2 = LODRenderData . GetIndex ( TriangleIndex * 3 + ( bReverseWinding ? 1 : 2 ) ) ;
}
2019-09-14 09:45:25 -04:00
void FStaticMeshStaticLightingMesh : : GetNonTransformedTriangleIndices ( int32 TriangleIndex , int32 & OutI0 , int32 & OutI1 , int32 & OutI2 ) const
{
const FStaticMeshLOD & LODRenderData = StaticMesh - > GetLOD ( GetMeshLODIndex ( ) ) ;
// Lookup the triangle's vertex indices.
OutI0 = LODRenderData . GetIndex ( TriangleIndex * 3 + 0 ) ;
OutI1 = LODRenderData . GetIndex ( TriangleIndex * 3 + 1 ) ;
OutI2 = LODRenderData . GetIndex ( TriangleIndex * 3 + 2 ) ;
}
2014-03-14 14:13:41 -04:00
bool FStaticMeshStaticLightingMesh : : IsElementCastingShadow ( int32 ElementIndex ) const
{
const FStaticMeshLOD & LODRenderData = StaticMesh - > GetLOD ( GetMeshLODIndex ( ) ) ;
const FStaticMeshElement & Element = LODRenderData . GetElement ( ElementIndex ) ;
return Element . bEnableShadowCasting ;
}
void FStaticMeshStaticLightingMesh : : Import ( FLightmassImporter & Importer )
{
// import super class
FStaticLightingMesh : : Import ( Importer ) ;
// import the shared data
// Importer.ImportData( (FStaticMeshStaticLightingMeshData*) this );
FStaticMeshStaticLightingMeshData TempSMSLMD ;
Importer . ImportData ( & TempSMSLMD ) ;
2015-10-06 15:59:09 -04:00
EncodedLODIndices = TempSMSLMD . EncodedLODIndices ;
EncodedHLODRange = TempSMSLMD . EncodedHLODRange ;
2014-03-14 14:13:41 -04:00
LocalToWorld = TempSMSLMD . LocalToWorld ;
bReverseWinding = TempSMSLMD . bReverseWinding ;
bShouldSelfShadow = TempSMSLMD . bShouldSelfShadow ;
StaticMeshGuid = TempSMSLMD . StaticMeshGuid ;
bIsSplineMesh = TempSMSLMD . bIsSplineMesh ;
SplineParameters = TempSMSLMD . SplineParameters ;
// calculate the inverse transpose
2019-09-14 09:45:25 -04:00
WorldToLocal = LocalToWorld . InverseFast ( ) ;
2014-08-13 15:29:41 -04:00
LocalToWorldInverseTranspose = LocalToWorld . InverseFast ( ) . GetTransposed ( ) ;
2014-03-14 14:13:41 -04:00
// we have the guid for the mesh, now hook it up to the actual static mesh
StaticMesh = Importer . ConditionalImportObject < FStaticMesh > ( StaticMeshGuid , LM_STATICMESH_VERSION , LM_STATICMESH_EXTENSION , LM_STATICMESH_CHANNEL_FLAGS , Importer . GetStaticMeshes ( ) ) ;
checkf ( StaticMesh , TEXT ( " Failed to import static mesh with GUID %s " ) , * StaticMeshGuid . ToString ( ) ) ;
check ( GetMeshLODIndex ( ) > = 0 & & GetMeshLODIndex ( ) < ( int32 ) StaticMesh - > NumLODs ) ;
checkf ( StaticMesh - > GetLOD ( GetMeshLODIndex ( ) ) . NumElements = = MaterialElements . Num ( ) , TEXT ( " Static mesh element count did not match mesh instance element count! " ) ) ;
}
void FStaticMeshStaticLightingTextureMapping : : Import ( FLightmassImporter & Importer )
{
// import the super class
FStaticLightingTextureMapping : : Import ( Importer ) ;
check ( Mesh ) ;
}
} //namespace Lightmass