// Copyright Epic Games, Inc. All Rights Reserved. #include "AssetUtils/MeshDescriptionUtil.h" #include "Engine/StaticMesh.h" #include "Engine/Classes/Components/StaticMeshComponent.h" #include "StaticMeshAttributes.h" #include "StaticMeshOperations.h" void UE::MeshDescription::InitializeAutoGeneratedAttributes(FMeshDescription& Mesh, const FMeshBuildSettings* BuildSettings) { check(BuildSettings); // if the build settings don't indicate calculated normals/tangents, we will assume they are good if (BuildSettings->bRecomputeNormals || BuildSettings->bRecomputeTangents) { // check if any are invalid bool bHasInvalidNormals, bHasInvalidTangents; FStaticMeshOperations::AreNormalsAndTangentsValid(Mesh, bHasInvalidNormals, bHasInvalidTangents); // if neither are invalid we are not going to recompute if (bHasInvalidNormals || bHasInvalidTangents) { FStaticMeshAttributes Attributes(Mesh); if (!Attributes.GetTriangleNormals().IsValid() || !Attributes.GetTriangleTangents().IsValid()) { // If these attributes don't exist, create them and compute their values for each triangle FStaticMeshOperations::ComputeTriangleTangentsAndNormals(Mesh); } EComputeNTBsFlags ComputeNTBsOptions = EComputeNTBsFlags::BlendOverlappingNormals; ComputeNTBsOptions |= BuildSettings->bRecomputeNormals ? EComputeNTBsFlags::Normals : EComputeNTBsFlags::None; ComputeNTBsOptions |= BuildSettings->bRecomputeTangents ? EComputeNTBsFlags::Tangents : EComputeNTBsFlags::None; ComputeNTBsOptions |= BuildSettings->bUseMikkTSpace ? EComputeNTBsFlags::UseMikkTSpace : EComputeNTBsFlags::None; ComputeNTBsOptions |= BuildSettings->bComputeWeightedNormals ? EComputeNTBsFlags::WeightedNTBs : EComputeNTBsFlags::None; ComputeNTBsOptions |= BuildSettings->bRemoveDegenerates ? EComputeNTBsFlags::IgnoreDegenerateTriangles : EComputeNTBsFlags::None; FStaticMeshOperations::ComputeTangentsAndNormals(Mesh, ComputeNTBsOptions); } } } void UE::MeshDescription::InitializeAutoGeneratedAttributes(FMeshDescription& Mesh, UStaticMesh* StaticMesh, int32 SourceLOD) { #if WITH_EDITOR if (ensureMsgf(SourceLOD < StaticMesh->GetNumSourceModels(), TEXT("InitializeMeshDescription requested LOD index greater than num available in UStaticMesh"))) { const FStaticMeshSourceModel& SourceModel = StaticMesh->GetSourceModel(SourceLOD); InitializeAutoGeneratedAttributes(Mesh, &SourceModel.BuildSettings); } #else ensureMsgf(false, TEXT("InitializeMeshDescription requires Editor-only SourceModel field of UStaticMesh")); #endif } void UE::MeshDescription::InitializeAutoGeneratedAttributes(FMeshDescription& Mesh, UActorComponent* StaticMeshComponent, int32 SourceLOD) { #if WITH_EDITOR if (Cast(StaticMeshComponent) != nullptr) { UStaticMesh* StaticMesh = Cast(StaticMeshComponent)->GetStaticMesh(); if (ensure(StaticMesh != nullptr)) { InitializeAutoGeneratedAttributes(Mesh, StaticMesh, SourceLOD); } } #else //ensureMsgf(false, TEXT("InitializeMeshDescription requires Editor-only SourceModel field of UStaticMesh")); #endif } void UE::MeshDescription::ConfigureBuildSettings(UStaticMesh* StaticMesh, int32 SourceLOD, FStaticMeshBuildSettingChange NewSettings) { #if WITH_EDITOR if (ensureMsgf(SourceLOD < StaticMesh->GetNumSourceModels(), TEXT("ConfigureBuildSettings requested LOD index greater than num available in UStaticMesh"))) { FStaticMeshSourceModel& SourceModel = StaticMesh->GetSourceModel(SourceLOD); if (NewSettings.AutoGeneratedNormals != EBuildSettingBoolChange::NoChange) { SourceModel.BuildSettings.bRecomputeNormals = (NewSettings.AutoGeneratedNormals == EBuildSettingBoolChange::Disable) ? false : true; } if (NewSettings.AutoGeneratedTangents != EBuildSettingBoolChange::NoChange) { SourceModel.BuildSettings.bRecomputeTangents = (NewSettings.AutoGeneratedTangents == EBuildSettingBoolChange::Disable) ? false : true; } if (NewSettings.UseMikkTSpaceTangents != EBuildSettingBoolChange::NoChange) { SourceModel.BuildSettings.bUseMikkTSpace = (NewSettings.UseMikkTSpaceTangents == EBuildSettingBoolChange::Disable) ? false : true; } } #else // just ignore? #endif }