feat: 添加调试可视化工具和性能优化

- Task 10: 添加调试可视化工具
  - DebugDrawFlowDirections() - 可视化材料流动方向
  - DebugDrawEdgeVertices() - 可视化边缘顶点
  - DebugPrintVertexAttributes() - 输出顶点属性统计信息

- Task 12: 性能优化和参数调优
  - 添加 bEnableAdaptiveOptimization 参数
  - 添加 MinSmoothingInterval 参数
  - 添加 LastHammerImpactTime 追踪
  - 在OnHammerImpact中应用自适应优化逻辑

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 22:49:06 +08:00
parent c6d21201dd
commit 07d2a322a4
2 changed files with 201 additions and 3 deletions
+170 -3
View File
@@ -307,6 +307,9 @@ void ADynamicIronBlock::OnHammerImpact(FVector HitLocation, FVector HitNormal, f
UE_LOG(LogTemp, Log, TEXT("DynamicIronBlock: Hammer impact at local position (%f, %f, %f), depth: %f, radius: %f, anisotropy: %f"),
LocalHitLocation.X, LocalHitLocation.Y, LocalHitLocation.Z, ActualDepth, ImpactRadius, AnisotropyRatio);
// 记录锤击时间
float CurrentTime = GetWorld()->GetTimeSeconds();
// 计算材料流动方向
FVector BoxHalfSize = BoxSize * 0.5f;
FVector ToNearestEdge = FindNearestFreeEdgeDirection(LocalHitLocation, BoxHalfSize);
@@ -441,9 +444,18 @@ void ADynamicIronBlock::OnHammerImpact(FVector HitLocation, FVector HitNormal, f
}
}
// 应用Laplacian平滑(轻微,保持形状细节)
float BulgeOuterRadius = ImpactRadius * (1.0f + BulgeRatio);
ApplyLaplacianSmoothing(EditMesh, LocalHitLocation, BulgeOuterRadius, 0.1f);
// 自适应优化:仅在锤击间隔足够大时执行完整平滑
bool bShouldSmooth = !bEnableAdaptiveOptimization || (CurrentTime - LastHammerImpactTime > MinSmoothingInterval);
if (bShouldSmooth)
{
// 应用Laplacian平滑(轻微,保持形状细节)
float BulgeOuterRadius = ImpactRadius * (1.0f + BulgeRatio);
ApplyLaplacianSmoothing(EditMesh, LocalHitLocation, BulgeOuterRadius, 0.1f);
}
// 更新上次锤击时间
LastHammerImpactTime = CurrentTime;
}, EDynamicMeshChangeType::GeneralEdit, EDynamicMeshAttributeChangeFlags::Unknown, false);
// 重新计算法线
@@ -1616,3 +1628,158 @@ void ADynamicIronBlock::ApplyLaplacianSmoothing(FDynamicMesh3& Mesh, const FVect
Mesh.SetVertex(Pair.Key, Pair.Value);
}
}
// ========== 调试可视化工具实现 ==========
void ADynamicIronBlock::DebugDrawFlowDirections()
{
if (!GetWorld())
return;
UDynamicMeshComponent* DynMeshComp = GetDynamicMeshComponent();
if (!DynMeshComp)
return;
UDynamicMesh* DynMesh = DynMeshComp->GetDynamicMesh();
if (!DynMesh)
return;
FVector BoxHalfSize = BoxSize * 0.5f;
// 在网格表面采样点
DynMesh->ProcessMesh([&](const FDynamicMesh3& ReadMesh)
{
int32 SampleCount = 0;
for (int32 VertexID : ReadMesh.VertexIndicesItr())
{
// 每100个顶点采样一次
if (SampleCount++ % 100 != 0)
continue;
FVector3d Pos3d = ReadMesh.GetVertex(VertexID);
FVector Pos(Pos3d.X, Pos3d.Y, Pos3d.Z);
// 计算流动方向
FVector ToNearestEdge = FindNearestFreeEdgeDirection(Pos, BoxHalfSize);
FVector PrimaryFlow = CalculatePrimaryFlowDirection(FVector::DownVector, ToNearestEdge);
// 转换到世界坐标
FVector WorldPos = GetActorTransform().TransformPosition(Pos);
FVector WorldDir = GetActorTransform().TransformVector(PrimaryFlow);
// 绘制方向箭头
DrawDebugDirectionalArrow(
GetWorld(),
WorldPos,
WorldPos + WorldDir * 5.0f,
100.0f, // 箭头大小
FColor::Cyan,
false, // 是否持久
5.0f, // 持续时间
0, // 深度优先级
0.5f // 箭头厚度
);
}
});
UE_LOG(LogTemp, Warning, TEXT("DynamicIronBlock: Flow direction debug visualization drawn"));
}
void ADynamicIronBlock::DebugDrawEdgeVertices()
{
if (!GetWorld())
return;
UDynamicMeshComponent* DynMeshComp = GetDynamicMeshComponent();
if (!DynMeshComp)
return;
UDynamicMesh* DynMesh = DynMeshComp->GetDynamicMesh();
if (!DynMesh)
return;
TSet<int32> EdgeVertices;
DynMesh->ProcessMesh([&](const FDynamicMesh3& ReadMesh)
{
MarkEdgeVertices(ReadMesh, EdgeVertices);
});
for (int32 VID : EdgeVertices)
{
DynMesh->ProcessMesh([&](const FDynamicMesh3& ReadMesh)
{
if (!ReadMesh.IsVertex(VID))
return;
FVector3d Pos3d = ReadMesh.GetVertex(VID);
FVector WorldPos = GetActorTransform().TransformPosition(FVector(Pos3d.X, Pos3d.Y, Pos3d.Z));
DrawDebugPoint(GetWorld(), WorldPos, 8.0f, FColor::Red, false, 5.0f);
});
}
UE_LOG(LogTemp, Warning, TEXT("DynamicIronBlock: Edge vertices debug visualization drawn (%d vertices)"), EdgeVertices.Num());
}
void ADynamicIronBlock::DebugPrintVertexAttributes()
{
UDynamicMeshComponent* DynMeshComp = GetDynamicMeshComponent();
if (!DynMeshComp)
return;
UDynamicMesh* DynMesh = DynMeshComp->GetDynamicMesh();
if (!DynMesh)
return;
if (!bVertexAttributesInitialized)
{
UE_LOG(LogTemp, Warning, TEXT("DynamicIronBlock: Vertex attributes not initialized"));
return;
}
// 统计信息
float MinStrain = FLT_MAX, MaxStrain = -FLT_MAX, AvgStrain = 0.0f;
float MinPolish = FLT_MAX, MaxPolish = -FLT_MAX, AvgPolish = 0.0f;
int32 Count = 0;
DynMesh->ProcessMesh([&](const FDynamicMesh3& ReadMesh)
{
for (int32 VertexID : ReadMesh.VertexIndicesItr())
{
if (!AccumulatedStrainArray.IsValidIndex(VertexID) || !PolishAmountArray.IsValidIndex(VertexID))
continue;
float Strain = AccumulatedStrainArray[VertexID];
float Polish = PolishAmountArray[VertexID];
MinStrain = FMath::Min(MinStrain, Strain);
MaxStrain = FMath::Max(MaxStrain, Strain);
AvgStrain += Strain;
MinPolish = FMath::Min(MinPolish, Polish);
MaxPolish = FMath::Max(MaxPolish, Polish);
AvgPolish += Polish;
Count++;
}
});
if (Count > 0)
{
AvgStrain /= Count;
AvgPolish /= Count;
}
UE_LOG(LogTemp, Warning, TEXT("========== Vertex Attributes Debug =========="));
UE_LOG(LogTemp, Warning, TEXT("Vertices: %d"), Count);
UE_LOG(LogTemp, Warning, TEXT("Strain: Min=%.3f, Max=%.3f, Avg=%.3f"), MinStrain, MaxStrain, AvgStrain);
UE_LOG(LogTemp, Warning, TEXT("Polish: Min=%.3f, Max=%.3f, Avg=%.3f"), MinPolish, MaxPolish, AvgPolish);
UE_LOG(LogTemp, Warning, TEXT("==========================================="));
// 屏幕显示
if (GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow,
FString::Printf(TEXT("Strain: Avg=%.2f | Polish: Avg=%.2f"), AvgStrain, AvgPolish));
}
}
+31
View File
@@ -86,6 +86,16 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Iron Block|Material Properties", meta = (ClampMin = "0.1", ClampMax = "5.0"))
float EdgeThreshold = 0.5f;
// ========== 性能参数 ==========
// 是否启用自适应优化(仅在锤击间隔较长时执行完整优化)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Iron Block|Performance")
bool bEnableAdaptiveOptimization = true;
// 最小平滑间隔(秒,低于此值跳过平滑)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Iron Block|Performance", meta = (ClampMin = "0.0", ClampMax = "1.0"))
float MinSmoothingInterval = 0.1f;
// ========== 温度系统参数 ==========
// 温度体素大小(毫米)
@@ -160,6 +170,24 @@ public:
UFUNCTION(BlueprintCallable, Category = "Temperature System|Debug")
void DebugPrintVertexColors();
/**
* 调试函数 - 可视化材料流动方向
*/
UFUNCTION(BlueprintCallable, Category = "Hammer Impact|Debug")
void DebugDrawFlowDirections();
/**
* 调试函数 - 可视化边缘顶点
*/
UFUNCTION(BlueprintCallable, Category = "Hammer Impact|Debug")
void DebugDrawEdgeVertices();
/**
* 调试函数 - 输出顶点属性统计信息
*/
UFUNCTION(BlueprintCallable, Category = "Hammer Impact|Debug")
void DebugPrintVertexAttributes();
protected:
// 当游戏开始或生成时调用
virtual void BeginPlay() override;
@@ -302,6 +330,9 @@ private:
// 标志位:顶点属性是否已初始化
bool bVertexAttributesInitialized = false;
// 上次锤击时间(用于自适应优化)
float LastHammerImpactTime = 0.0f;
/**
* 初始化顶点属性层
*/