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:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* 初始化顶点属性层
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user