feat: 实现打磨度系统和网格质量维护

- Task 7: 实现打磨度在锤击时的更新
  - 在OnHammerImpact中添加打磨度更新逻辑
  - 打磨度与形变量成正比

- Task 8: 更新顶点颜色以编码打磨度
  - 修改UpdateVertexColors函数支持打磨度
  - 添加生锈颜色(深红褐色)到金属颜色(亮银色)的混合
  - 最终颜色 = 温度颜色 * 打磨颜色

- Task 9: 添加基础Laplacian平滑
  - 实现ApplyLaplacianSmoothing函数
  - 在OnHammerImpact中调用平滑以维护网格质量

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 22:47:15 +08:00
parent 3c05d0f845
commit c6d21201dd
2 changed files with 83 additions and 2 deletions
+78 -2
View File
@@ -399,6 +399,16 @@ void ADynamicIronBlock::OnHammerImpact(FVector HitLocation, FVector HitNormal, f
float StrainDelta = Displacement.Size();
AccumulatedStrainArray[VertexID] = CurrentStrain + StrainDelta;
}
// 更新打磨度(锤击使表面变亮)
if (bVertexAttributesInitialized && PolishAmountArray.IsValidIndex(VertexID))
{
float CurrentPolish = PolishAmountArray[VertexID];
// 打磨度增加量与形变量成正比
float PolishIncrease = Displacement.Size() * 0.5f;
float NewPolish = FMath::Clamp(CurrentPolish + PolishIncrease, 0.0f, 1.0f);
PolishAmountArray[VertexID] = NewPolish;
}
}
}
@@ -430,6 +440,10 @@ void ADynamicIronBlock::OnHammerImpact(FVector HitLocation, FVector HitNormal, f
UE_LOG(LogTemp, Log, TEXT("DynamicIronBlock: Applied edge constraint to %d vertices"), AffectedEdges.Num());
}
}
// 应用Laplacian平滑(轻微,保持形状细节)
float BulgeOuterRadius = ImpactRadius * (1.0f + BulgeRatio);
ApplyLaplacianSmoothing(EditMesh, LocalHitLocation, BulgeOuterRadius, 0.1f);
}, EDynamicMeshChangeType::GeneralEdit, EDynamicMeshAttributeChangeFlags::Unknown, false);
// 重新计算法线
@@ -937,12 +951,33 @@ void ADynamicIronBlock::UpdateVertexColors()
// 将温度转换为黑体辐射颜色
FLinearColor TempColor = TemperatureToColor(Temperature);
VertexColors.Add(TempColor);
// 获取打磨度并混合颜色
float Polish = 0.2f; // 默认值
if (bVertexAttributesInitialized && PolishAmountArray.IsValidIndex(VertexID))
{
Polish = PolishAmountArray[VertexID];
}
// 生锈颜色(深红褐色)
FLinearColor RustColor(0.4f, 0.2f, 0.15f);
// 金属颜色(亮银色)
FLinearColor MetalColor(0.9f, 0.9f, 0.95f);
// 根据打磨度混合:0=生锈,1=光亮金属
FLinearColor PolishColor = FMath::Lerp(RustColor, MetalColor, Polish);
// 最终颜色 = 温度颜色 * 打磨颜色(乘法混合)
FLinearColor FinalColor = TempColor * PolishColor;
FinalColor.A = 1.0f; // 不透明
VertexColors.Add(FinalColor);
// 记录第一个有效顶点的信息用于调试
if (VertexID == 0)
{
FirstVertexColor = TempColor;
FirstVertexColor = FinalColor;
FirstVertexTemp = Temperature;
FirstVertexPos = VertexPosFloat;
}
@@ -1540,3 +1575,44 @@ void ADynamicIronBlock::ApplyEdgeLinearConstraint(FDynamicMesh3& Mesh, const TSe
}
}
}
void ADynamicIronBlock::ApplyLaplacianSmoothing(FDynamicMesh3& Mesh, const FVector& Center, float Radius, float Alpha)
{
// 创建位置副本用于迭代计算
TMap<int32, FVector3d> NewPositions;
for (int32 VertexID : Mesh.VertexIndicesItr())
{
FVector3d VertexPos = Mesh.GetVertex(VertexID);
FVector PosFloat(VertexPos.X, VertexPos.Y, VertexPos.Z);
// 只处理影响范围内的顶点
if (FVector::Dist(PosFloat, Center) > Radius)
continue;
// 计算Laplacian(邻居顶点的平均位置)
FVector3d Laplacian(0.0, 0.0, 0.0);
int32 NeighborCount = 0;
for (int32 NbrVID : Mesh.VtxVerticesItr(VertexID))
{
Laplacian += Mesh.GetVertex(NbrVID);
NeighborCount++;
}
if (NeighborCount > 0)
{
Laplacian /= NeighborCount;
// 平滑更新:新位置 = 原位置 + Alpha * (Laplacian - 原位置)
FVector3d SmoothPos = FMath::Lerp(VertexPos, Laplacian, Alpha);
NewPositions.Add(VertexID, SmoothPos);
}
}
// 应用新位置
for (const TPair<int32, FVector3d>& Pair : NewPositions)
{
Mesh.SetVertex(Pair.Key, Pair.Value);
}
}
+5
View File
@@ -341,6 +341,11 @@ private:
*/
void ApplyEdgeLinearConstraint(FDynamicMesh3& Mesh, const TSet<int32>& EdgeVertices);
/**
* 应用Laplacian平滑到受影响区域
*/
void ApplyLaplacianSmoothing(FDynamicMesh3& Mesh, const FVector& Center, float Radius, float Alpha = 0.3f);
// ========== GPU计算系统(Phase 2) ==========
// GPU缓冲区(Ping-Pong双缓冲)