diff --git a/.claude/settings.local.json b/.claude/settings.local.json index ed13a4d..38add98 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -7,7 +7,9 @@ "Bash(dir:*)", "Bash(git add:*)", "Bash(git commit -m \"$(cat <<''EOF''\n实现DynamicIronBlock温度体素系统基础功能\n\n新增功能:\n- 添加FTemperatureVoxel结构体(温度、塑性系数、表面标志)\n- 实现自适应温度网格(5mm体素精度,基于BoxSize计算分辨率)\n- 实现三线性插值温度/塑性系数采样\n- 实现黑体辐射温度可视化(顶点颜色)\n- 添加HeatRegion蓝图测试函数\n- 添加OnHammerImpact锤击形变函数(体积守恒)\n\n技术细节:\n- Phase 1: CPU侧温度网格初始化,支持10cm-100cm+可变尺寸\n- Phase 3: 温度可视化系统(20°C灰色 → 1200°C白色)\n- 内存占用:30×30×30cm ≈ 1.7MB(60×60×60体素)\n\n待实现:Phase 2 GPU热传导计算\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude \nEOF\n)\")", - "Bash(git commit:*)" + "Bash(git commit:*)", + "Bash(\"E:\\MiceCola\\work\\UE_5_6\\Engine\\Build\\BatchFiles\\Build.bat\" BladeSmithEditor Win64 Development -Project=\"C:\\MiceCola\\Indi\\BladeSmith\\BladeSmith.uproject\" -WaitMutex -FromMsBuild)", + "Bash(cmd /c:*)" ], "deny": [], "ask": [] diff --git a/Content/Maps/Demo.umap b/Content/Maps/Demo.umap index 2529712..641995f 100644 Binary files a/Content/Maps/Demo.umap and b/Content/Maps/Demo.umap differ diff --git a/Content/Res/Materials/M_VertexColor.uasset b/Content/Res/Materials/M_VertexColor.uasset index 9d2b14c..92c3d7e 100644 Binary files a/Content/Res/Materials/M_VertexColor.uasset and b/Content/Res/Materials/M_VertexColor.uasset differ diff --git a/Content/Res/Materials/Metal/M_DynamicIron.uasset b/Content/Res/Materials/Metal/M_DynamicIron.uasset index 3bee32b..e6fe62f 100644 Binary files a/Content/Res/Materials/Metal/M_DynamicIron.uasset and b/Content/Res/Materials/Metal/M_DynamicIron.uasset differ diff --git a/Source/BladeSmith/DynamicIronBlock.cpp b/Source/BladeSmith/DynamicIronBlock.cpp index 67b2498..c5eb10c 100644 --- a/Source/BladeSmith/DynamicIronBlock.cpp +++ b/Source/BladeSmith/DynamicIronBlock.cpp @@ -66,6 +66,7 @@ void ADynamicIronBlock::Tick(float DeltaTime) return; } + // ========== 温度计算更新 ========== // 累积时间 TimeSinceLastUpdate += DeltaTime; @@ -78,9 +79,37 @@ void ADynamicIronBlock::Tick(float DeltaTime) // 重置计时器 TimeSinceLastUpdate = 0.0f; - // 从GPU下载温度数据并更新顶点颜色 + // 从GPU下载温度数据并更新材质参数 DownloadTemperatureDataFromGPU(); - // 注意:UpdateVertexColors()会在DownloadTemperatureDataFromGPU的回调中异步调用 + // 注意:UpdateMaterialTemperature()会在DownloadTemperatureDataFromGPU的回调中异步调用 + } + + // ========== 自动加热功能 ========== + if (bIsHeating) + { + // 累积加热时间 + TimeSinceLastHeating += DeltaTime; + + // 每隔HeatingInterval进行一次加热 + if (TimeSinceLastHeating >= HeatingInterval) + { + // 获取铁块中心位置(世界坐标) + FVector WorldCenter = GetActorLocation(); + + // 执行加热 + HeatRegion(WorldCenter, HeatingRadius, HeatingTemperatureIncrease); + + // 重置加热计时器 + TimeSinceLastHeating = 0.0f; + + UE_LOG(LogTemp, Log, TEXT("DynamicIronBlock: Auto heating applied at center, radius: %.2f cm, temp increase: %.2f °C"), + HeatingRadius, HeatingTemperatureIncrease); + } + } + else + { + // 如果加热被关闭,重置计时器 + TimeSinceLastHeating = 0.0f; } } @@ -153,7 +182,7 @@ void ADynamicIronBlock::InitializeBoxMesh() // 如果设置了材质,创建动态材质实例并应用 if (IronMaterial) { - UMaterialInstanceDynamic* DynamicMaterialInstance = UMaterialInstanceDynamic::Create(IronMaterial, this); + DynamicMaterialInstance = UMaterialInstanceDynamic::Create(IronMaterial, this); if (DynamicMaterialInstance) { DynMeshComp->SetMaterial(0, DynamicMaterialInstance); @@ -536,8 +565,8 @@ void ADynamicIronBlock::HeatRegion(FVector WorldCenter, float Radius, float Temp UE_LOG(LogTemp, Log, TEXT("DynamicIronBlock: Temperature data uploaded to GPU after HeatRegion")); } - // 更新顶点颜色以显示温度变化 - UpdateVertexColors(); + // 更新材质温度参数以显示温度变化 + UpdateMaterialTemperature(); } float ADynamicIronBlock::SampleTemperatureAtPosition(const FVector& LocalPosition) const @@ -680,54 +709,66 @@ FLinearColor ADynamicIronBlock::TemperatureToColor(float Temperature) const } } -void ADynamicIronBlock::UpdateVertexColors() +float ADynamicIronBlock::CalculateAverageTemperature() const +{ + if (!bEnableTemperatureSystem || TemperatureGrid.Num() == 0) + { + return AmbientTemperature; + } + + float TotalTemperature = 0.0f; + int32 ValidVoxels = 0; + + // 遍历所有体素,累加温度 + for (const FTemperatureVoxel& Voxel : TemperatureGrid) + { + TotalTemperature += Voxel.Temperature; + ++ValidVoxels; + } + + // 计算平均温度 + return ValidVoxels > 0 ? (TotalTemperature / ValidVoxels) : AmbientTemperature; +} + +void ADynamicIronBlock::UpdateMaterialTemperature() { if (!bEnableTemperatureSystem || TemperatureGrid.Num() == 0) { return; } - UDynamicMeshComponent* DynMeshComp = GetDynamicMeshComponent(); - if (!DynMeshComp) + if (!DynamicMaterialInstance) { + UE_LOG(LogTemp, Warning, TEXT("DynamicIronBlock: Cannot update material temperature, dynamic material instance is null")); return; } - UDynamicMesh* DynMesh = DynMeshComp->GetDynamicMesh(); - if (!DynMesh) + // 计算平均温度 + float AverageTemperature = CalculateAverageTemperature(); + + // 将温度映射到颜色 + FLinearColor TemperatureColor = TemperatureToColor(AverageTemperature); + + // 设置材质参数 + DynamicMaterialInstance->SetScalarParameterValue(FName("Temperature"), AverageTemperature); + DynamicMaterialInstance->SetVectorParameterValue(FName("TemperatureColor"), TemperatureColor); + + UE_LOG(LogTemp, Log, TEXT("DynamicIronBlock: Material temperature updated - Avg: %.1f°C, Color: (%.2f, %.2f, %.2f)"), + AverageTemperature, TemperatureColor.R, TemperatureColor.G, TemperatureColor.B); + + // 在屏幕上显示温度信息(保留3秒) + if (GEngine) { - return; + FString DebugMessage = FString::Printf(TEXT("Temperature: %.1f°C | Color: (R:%.2f, G:%.2f, B:%.2f)"), + AverageTemperature, TemperatureColor.R, TemperatureColor.G, TemperatureColor.B); + + GEngine->AddOnScreenDebugMessage( + -1, // Key (-1 表示自动分配) + 3.0f, // 显示时长(秒) + TemperatureColor.ToFColor(true), // 使用温度颜色 + DebugMessage + ); } - - DynMesh->EditMesh([&](FDynamicMesh3& EditMesh) - { - // 启用顶点颜色(如果尚未启用) - if (!EditMesh.HasVertexColors()) - { - EditMesh.EnableVertexColors(FVector3f(0.2f, 0.2f, 0.2f)); - } - - // 遍历所有顶点 - for (int32 VertexID : EditMesh.VertexIndicesItr()) - { - // 获取顶点位置(局部坐标) - FVector3d VertexPos = EditMesh.GetVertex(VertexID); - FVector VertexPosFloat(VertexPos.X, VertexPos.Y, VertexPos.Z); - - // 通过三线性插值获取该顶点的温度 - float Temperature = SampleTemperatureAtPosition(VertexPosFloat); - - // 将温度映射到颜色 - FLinearColor VertexColor = TemperatureToColor(Temperature); - - // 设置顶点颜色 - EditMesh.SetVertexColor(VertexID, FVector3f(VertexColor.R, VertexColor.G, VertexColor.B)); - } - }, EDynamicMeshChangeType::GeneralEdit, EDynamicMeshAttributeChangeFlags::Unknown, false); - - DynMeshComp->NotifyMeshUpdated(); - - UE_LOG(LogTemp, Log, TEXT("DynamicIronBlock: Vertex colors updated based on temperature")); } // ========== GPU缓冲区管理实现 ========== @@ -904,8 +945,8 @@ void ADynamicIronBlock::DownloadTemperatureDataFromGPU() UE_LOG(LogTemp, Log, TEXT("DynamicIronBlock: Temperature data downloaded from GPU")); - // 更新顶点颜色以反映新的温度 - UpdateVertexColors(); + // 更新材质温度参数以反映新的温度 + UpdateMaterialTemperature(); }); }); } diff --git a/Source/BladeSmith/DynamicIronBlock.h b/Source/BladeSmith/DynamicIronBlock.h index 48a841b..7849e11 100644 --- a/Source/BladeSmith/DynamicIronBlock.h +++ b/Source/BladeSmith/DynamicIronBlock.h @@ -104,6 +104,24 @@ public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Temperature System") bool bEnableTemperatureSystem = true; + // ========== 自动加热功能 ========== + + // 是否正在加热中 + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Temperature System|Auto Heating") + bool bIsHeating = false; + + // 自动加热间隔(秒) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Temperature System|Auto Heating", meta = (ClampMin = "0.1", ClampMax = "10.0")) + float HeatingInterval = 1.0f; + + // 自动加热半径(厘米) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Temperature System|Auto Heating") + float HeatingRadius = 30.0f; + + // 每次加热温度增量(摄氏度) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Temperature System|Auto Heating") + float HeatingTemperatureIncrease = 100.0f; + /** * 测试函数 - 加热指定区域 * @param WorldCenter 加热中心位置(世界坐标) @@ -156,6 +174,10 @@ private: // 温度网格分辨率 FIntVector TemperatureResolution; + // 动态材质实例(用于更新温度参数) + UPROPERTY() + UMaterialInstanceDynamic* DynamicMaterialInstance; + // ========== 温度系统方法 ========== /** @@ -235,9 +257,15 @@ private: FLinearColor TemperatureToColor(float Temperature) const; /** - * 更新网格顶点颜色以显示温度 + * 计算平均温度 + * @return 体素网格的平均温度 */ - void UpdateVertexColors(); + float CalculateAverageTemperature() const; + + /** + * 更新动态材质的温度参数 + */ + void UpdateMaterialTemperature(); // ========== GPU计算系统(Phase 2) ========== @@ -259,6 +287,9 @@ private: float TimeSinceLastUpdate = 0.0f; // 距离上次温度更新的时间 float TemperatureUpdateInterval = 1.0f; // 温度更新间隔(秒) + // 自动加热计时器 + float TimeSinceLastHeating = 0.0f; // 距离上次自动加热的时间 + // GPU缓冲区是否已准备好(线程安全标志) std::atomic bGPUBuffersReady{false};