void FPaperSpriteVertex::SetTangentsFromPaperAxes()
{
	PackedNormalX = PaperAxisX;
	PackedNormalZ = PaperAxisZ;
	// store determinant of basis in w component of normal vector
	PackedNormalZ.Vector.W = (GetBasisDeterminantSign(PaperAxisX, PaperAxisY, PaperAxisZ) < 0.0f) ? 0 : 255;
}
void URuntimeMeshLibrary::CalculateTangentsForMeshPacked(TArray<FRuntimeMeshBlueprintVertexSimple>& Vertices, const TArray<int32>& Triangles, bool bCreateSmoothNormals)
{
	CalculateTangentsForMesh(
		[&Triangles](int32 Index) -> int32 { return Triangles[Index]; },
		[&Vertices](int32 Index) -> FVector { return Vertices[Index].Position; },
		[&Vertices](int32 Index) -> FVector2D { return Vertices[Index].UV0; },
		[&Vertices](int32 Index, FVector TangentX, FVector TangentY, FVector TangentZ)
		{
			Vertices[Index].Normal = TangentZ;
			Vertices[Index].Tangent.TangentX = TangentX;
			Vertices[Index].Tangent.bFlipTangentY = GetBasisDeterminantSign(TangentX, TangentY, TangentZ) < 0;
		},
		Vertices.Num(), Vertices.Num(), Triangles.Num(), bCreateSmoothNormals);
}
void URuntimeMeshLibrary::CalculateTangentsForMesh(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, TArray<FVector>& Normals, 
	const TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents, bool bCreateSmoothNormals)
{
	Normals.SetNum(Vertices.Num());
	Tangents.SetNum(Vertices.Num());
	CalculateTangentsForMesh(
		[&Triangles](int32 Index) -> int32 { return Triangles[Index]; },
		[&Vertices](int32 Index) -> FVector { return Vertices[Index]; },
		[&UVs](int32 Index) -> FVector2D { return UVs[Index]; },
		[&Normals, &Tangents](int32 Index, FVector TangentX, FVector TangentY, FVector TangentZ)
		{
			Normals[Index] = TangentZ;
			Tangents[Index].TangentX = TangentX;
			Tangents[Index].bFlipTangentY = GetBasisDeterminantSign(TangentX, TangentY, TangentZ) < 0;
		},
		Vertices.Num(), UVs.Num(), Triangles.Num(), bCreateSmoothNormals);
}
void URuntimeMeshLibrary::GetStaticMeshSection(UStaticMesh* InMesh, int32 LODIndex, int32 SectionIndex, TArray<FVector>& Vertices, TArray<int32>& Triangles,
	TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FColor>& Colors, TArray<FRuntimeMeshTangent>& Tangents)
{
	Vertices.Empty();
	Triangles.Empty();
	Normals.Empty();
	UVs.Empty();
	Colors.Empty();
	Tangents.Empty();

	GetStaticMeshSection(InMesh, LODIndex, SectionIndex, 1,
		[&Vertices, &Normals, &Tangents](FVector Position, FVector TangentX, FVector TangentY, FVector TangentZ) -> int32
		{
			int32 NewIndex = Vertices.Add(Position);
			Normals.Add(TangentZ);
			Tangents.Add(FRuntimeMeshTangent(TangentX, GetBasisDeterminantSign(TangentX, TangentY, TangentZ) < 0));
			return NewIndex;
		},
		[&UVs](int32 Index, int32 UVIndex, FVector2D UV)
		{
			check(UVIndex == 0);
			UVs.SetNum(Index + 1);
			UVs[Index] = UV;
		},
		[&Colors](int32 Index, FColor Color)
		{
			Colors.SetNum(Index + 1);
			Colors[Index] = Color;
		},
		[&Triangles](int32 Index)
		{
			Triangles.Add(Index);
		},
		[](int32 Index)
		{
		});
}
void URuntimeMeshLibrary::GetStaticMeshSectionPacked(UStaticMesh* InMesh, int32 LODIndex, int32 SectionIndex, TArray<FRuntimeMeshBlueprintVertexSimple>& Vertices, TArray<int32>& Triangles)
{
	Vertices.Empty();
	Triangles.Empty();

	GetStaticMeshSection(InMesh, LODIndex, SectionIndex, 1,
		[&Vertices](FVector Position, FVector TangentX, FVector TangentY, FVector TangentZ) -> int32
		{
			return Vertices.Add(FRuntimeMeshBlueprintVertexSimple(Position, TangentZ, FRuntimeMeshTangent(TangentX, GetBasisDeterminantSign(TangentX, TangentY, TangentZ) < 0), FVector2D::ZeroVector));
		},
		[&Vertices](int32 Index, int32 UVIndex, FVector2D UV)
		{
			check(UVIndex == 0);
			Vertices[Index].UV0 = UV;
		},
		[&Vertices](int32 Index, FColor Color)
		{
			Vertices[Index].Color = Color;
		},
		[&Triangles](int32 Index)
		{
			Triangles.Add(Index);
		},
		[](int32 Index)
		{
		});
}