不用每次动画结束都检测碰撞

This commit is contained in:
tian 2025-09-14 02:03:13 +08:00
parent 403a7ac03b
commit 6510a0e124

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Threading;
using Autodesk.Navisworks.Api;
@ -80,6 +81,7 @@ namespace NavisworksTransport.Core.Animation
public class PathAnimationManager
{
private static PathAnimationManager _instance;
private static readonly HashSet<string> _completedCollisionTests = new HashSet<string>(); // 记录已完成碰撞检测的动画配置
private ModelItem _animatedObject;
private List<Point3D> _pathPoints;
@ -89,6 +91,9 @@ namespace NavisworksTransport.Core.Animation
private HashSet<ModelItem> _currentHighlightedItems; // 当前高亮的对象
private List<CollisionResult> _allCollisionResults; // 所有碰撞结果(不去重)
private bool _lastHighlightState = false; // 上一帧的高亮状态
// === 碰撞测试优化 ===
private string _currentAnimationHash = ""; // 当前动画配置的哈希值
// === 动画播放机制 ===
private double _frameInterval; // 帧间隔(毫秒)
@ -237,6 +242,10 @@ namespace NavisworksTransport.Core.Animation
LogManager.Info("=== 坐标验证完成 ===");
// 计算并保存当前动画配置的哈希值
_currentAnimationHash = ComputeAnimationConfigHash(animatedObject, pathPoints);
LogManager.Info($"动画配置哈希: {_currentAnimationHash}");
_animatedObject = animatedObject;
_pathPoints = new List<Point3D>(pathPoints);
_animationDuration = durationSeconds;
@ -889,9 +898,22 @@ namespace NavisworksTransport.Core.Animation
_timeLinerManager.UpdateTaskProgress(_currentTaskId, 1.0, AnimationState.Finished);
}
// 动画结束后统一创建所有碰撞测试(使用预计算的所有碰撞结果)
LogManager.Info($"动画播放完成,开始创建最终的碰撞测试汇总(基于 {_allCollisionResults.Count} 个预计算碰撞记录)...");
ClashDetectiveIntegration.Instance.CreateAllAnimationCollisionTests(_allCollisionResults, _detectionGap);
// 检查此动画配置是否已经进行过碰撞检测
if (!_completedCollisionTests.Contains(_currentAnimationHash) && _allCollisionResults.Count > 0)
{
LogManager.Info($"此动画配置首次完成,开始创建碰撞测试汇总(基于 {_allCollisionResults.Count} 个预计算碰撞记录)...");
ClashDetectiveIntegration.Instance.CreateAllAnimationCollisionTests(_allCollisionResults, _detectionGap);
_completedCollisionTests.Add(_currentAnimationHash); // 记录此配置已完成碰撞检测
LogManager.Info($"碰撞测试汇总已创建并记录,此配置后续播放将跳过碰撞检测");
}
else if (_completedCollisionTests.Contains(_currentAnimationHash))
{
LogManager.Info("此动画配置的碰撞测试已存在,跳过重复创建");
}
else
{
LogManager.Info("无碰撞数据,跳过碰撞测试创建");
}
}
catch (Exception ex)
{
@ -2120,6 +2142,67 @@ namespace NavisworksTransport.Core.Animation
}
}
#region
/// <summary>
/// 计算动画配置的哈希值(基于路径点和对象)
/// </summary>
private string ComputeAnimationConfigHash(ModelItem animatedObject, List<Point3D> pathPoints)
{
try
{
var sb = new StringBuilder();
// 包含对象名称
sb.Append(animatedObject?.DisplayName ?? "null");
sb.Append("|");
// 包含路径点信息
if (pathPoints != null)
{
foreach (var point in pathPoints)
{
sb.Append($"{point.X:F2},{point.Y:F2},{point.Z:F2};");
}
}
// 计算哈希
using (var md5 = System.Security.Cryptography.MD5.Create())
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
var hashBytes = md5.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", "");
}
}
catch (Exception ex)
{
LogManager.Warning($"计算动画配置哈希失败: {ex.Message}");
return DateTime.Now.Ticks.ToString(); // 回退到时间戳
}
}
/// <summary>
/// 强制重新创建碰撞测试(清除指定配置的碰撞检测记录)
/// </summary>
public void ForceRecreateCollisionTest()
{
if (!string.IsNullOrEmpty(_currentAnimationHash))
{
_completedCollisionTests.Remove(_currentAnimationHash);
LogManager.Info($"已清除动画配置 {_currentAnimationHash} 的碰撞检测记录,下次播放时将重新创建");
}
}
/// <summary>
/// 清除所有碰撞测试记录
/// </summary>
public static void ClearAllCollisionTestRecords()
{
_completedCollisionTests.Clear();
LogManager.Info("已清除所有碰撞测试记录");
}
#endregion
#endregion
}