diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs index 59d820a..863dc24 100644 --- a/src/Core/Animation/PathAnimationManager.cs +++ b/src/Core/Animation/PathAnimationManager.cs @@ -349,29 +349,26 @@ namespace NavisworksTransport.Core.Animation _pathPoints = new List(pathPoints); _animationDuration = durationSeconds; - // 保存原始变换以便重置 - _originalTransform = _animatedObject.Transform; // 使用真正的Transform,不是自造的 + // 【统一逻辑修复】不再强制 Restore 到 CAD,而是继承物体的“当前”状态。 + // 这样如果物体已经通过 SyncToPathStart 移动到了起点并旋转,SetupAnimation 会直接复用该位置。 - // 获取并初始化当前偏航角 - _currentYaw = ModelItemTransformHelper.GetYawFromTransform(_originalTransform); - LogManager.Info($"[动画设置] 初始偏航角提取: {_currentYaw:F3}rad ({(_currentYaw * 180 / Math.PI):F1}度)"); + // 1. 获取物体的当前变换作为跟踪起点 + var currentTransform = _animatedObject.Transform; + _currentYaw = ModelItemTransformHelper.GetYawFromTransform(currentTransform); - // 保存车辆的原始中心位置 - var originalBoundingBox = animatedObject.BoundingBox(); - _originalCenter = originalBoundingBox.Center; - - // 初始化当前位置为物体底面中心,用于后续增量变换计算 + // 2. 初始化当前位置为物体当前的底面中心 + var currentBoundingBox = _animatedObject.BoundingBox(); _currentPosition = new Point3D( - _originalCenter.X, - _originalCenter.Y, - originalBoundingBox.Min.Z + currentBoundingBox.Center.X, + currentBoundingBox.Center.Y, + currentBoundingBox.Min.Z ); - // 调试:查看原始Transform的组成 - var origComponents = _originalTransform.Factor(); - LogManager.Info($"[原始Transform] Translation=({origComponents.Translation.X:F2},{origComponents.Translation.Y:F2},{origComponents.Translation.Z:F2})"); - LogManager.Info($"[原始Transform] Scale=({origComponents.Scale.X:F2},{origComponents.Scale.Y:F2},{origComponents.Scale.Z:F2})"); - LogManager.Info($"[原始Transform] 包围盒Center=({_originalCenter.X:F2},{_originalCenter.Y:F2},{_originalCenter.Z:F2})"); + LogManager.Info($"[动画设置] 继承当前位置和朝向:pos=({_currentPosition.X:F2},{_currentPosition.Y:F2},{_currentPosition.Z:F2}), yaw={_currentYaw:F3}rad"); + + // 调试:当前Transform的平移部分 + var components = currentTransform.Factor(); + LogManager.Info($"[当前Transform] Translation=({components.Translation.X:F2},{components.Translation.Y:F2},{components.Translation.Z:F2})"); // 预计算动画帧和碰撞 PrecomputeAnimationFrames(); @@ -382,8 +379,9 @@ namespace NavisworksTransport.Core.Animation throw new InvalidOperationException("动画帧预计算失败,无法创建动画"); } - // 将车辆移动到路径起点 - MoveVehicleToPathStart(); + // 【统一逻辑修复】移除 MoveVehicleToPathStart()。 + // 因为物体已经(在 UI 层或 SyncToPathStart)被移动到了正确位置, + // 且 SetupAnimation 已经继承了该位置,所以无需在此重新移动,避免“二次旋转”。 // 记录文档单位信息 var documentUnits = GetDocumentUnitsInfo(); @@ -529,7 +527,8 @@ namespace NavisworksTransport.Core.Animation var framePositions = new List(); for (int i = 0; i < totalFrames; i++) { - double progress = (double)i / totalFrames; + // 修正进度计算,确保最后一帧进度为 1.0 + double progress = totalFrames > 1 ? (double)i / (totalFrames - 1) : 0.0; var framePosition = InterpolatePosition(progress); framePositions.Add(framePosition); } @@ -537,7 +536,7 @@ namespace NavisworksTransport.Core.Animation // 第二遍:计算朝向并预计算每一帧 for (int i = 0; i < totalFrames; i++) { - double progress = (double)i / totalFrames; + double progress = totalFrames > 1 ? (double)i / (totalFrames - 1) : 0.0; var framePosition = framePositions[i]; // 计算朝向(基于前后帧) diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs index 4409016..a0e9d7e 100644 --- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs +++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs @@ -449,6 +449,20 @@ namespace NavisworksTransport.UI.WPF.ViewModels _pathAnimationManager.ClearAnimationResults(); // 清理手动选择物体留下的动画数据 LogManager.Info("已切换到虚拟车辆模式,将之前的手动选择物体归位并清理动画数据"); } + + // ✨ 统一逻辑:启用虚拟车辆时立即创建并对齐到起点 + if (VirtualVehicleManager.Instance.IsVirtualVehicleActive == false) + { + LogManager.Info("正在创建并初始化虚拟车辆到起点..."); + var vModel = VirtualVehicleManager.Instance.CreateVirtualVehicle( + VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight); + + if (vModel != null && CurrentPathRoute != null && CurrentPathRoute.Points != null) + { + var points = CurrentPathRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList(); + _pathAnimationManager?.SyncToPathStart(vModel, points); + } + } } catch (Exception ex) { @@ -1916,18 +1930,20 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (UseVirtualVehicle) { - // 使用虚拟车辆:创建真实的立方体几何体 - LogManager.Info($"[ExecuteGenerateAnimation] 准备创建虚拟车辆: " + - $"尺寸={VirtualVehicleLength:F1}m × {VirtualVehicleWidth:F1}m × {VirtualVehicleHeight:F1}m"); + // 使用虚拟车辆:优先获取已存在的实例 + animatedObject = VirtualVehicleManager.Instance.CurrentVirtualVehicle; - UpdateMainStatus("正在创建虚拟车辆...", -1, true); + if (animatedObject == null) + { + LogManager.Info("[ExecuteGenerateAnimation] 虚拟车辆不存在,正在创建..."); + UpdateMainStatus("正在创建虚拟车辆...", -1, true); - // 创建虚拟车辆几何体 - animatedObject = Core.VirtualVehicleManager.Instance.CreateVirtualVehicle( - VirtualVehicleLength, - VirtualVehicleWidth, - VirtualVehicleHeight - ); + animatedObject = Core.VirtualVehicleManager.Instance.CreateVirtualVehicle( + VirtualVehicleLength, + VirtualVehicleWidth, + VirtualVehicleHeight + ); + } if (animatedObject == null) { @@ -1936,7 +1952,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels return; } - LogManager.Info($"虚拟车辆创建成功: {animatedObject.DisplayName}"); + LogManager.Info($"使用虚拟车辆: {animatedObject.DisplayName}"); } else {