WPF 3D 平移模型+动画(桥梁检测系统)

2021-07-10 05:12

阅读:402

关于WPF 3D,网上有很多旋转的例子,但是关于平移的例子并不是太多。本文并非WPF 3D扫盲篇,因此需要对WPF 3D有一定了解,至少知道Viewport, PerspectiveCamera, ModelVisual3D等数据结构。需要了解WPF 3D的基础知识,可以参考MSDN:?http://msdn.microsoft.com/zh-cn/library/ms747437.aspx。

?

1. 摄像机平移OR物体平移:

WPF场景主要是由这两部分构成的:摄像机,物体。可以想象一下,自己拿着台摄像机正对着某个物体进行拍摄。

那么当发生平移的时候有两种方法,第一种是将摄像机平移;第二种是将物体平移。相对来说,摄像机平移实现较复杂,效率较高;物体平移效率较低,实现简单。

本文实现的是物体平移,如果希望做摄像机平移的朋友可以不往下读了。

?

2. 在本项目中平移的操作流程:?

1. 程序启动时可以看到整个3D场景,类似一个沙盘,此时旋转等操作会围绕沙盘中心;

2. 双击沙盘某个地方,将沙盘中心移动到双击的地方,此时旋转等操作会围绕新的沙盘中心。

?

3. 平移的算法:

1.获取双击屏幕后鼠标在3D中相对应的点,主要利用了射线和3D碰撞的一个原理。代码上主要应用的就是VisualTreeHelper.HitTest函数,它会将结果传入一个回调函数中,我们这里是HTResultCenter.

技术分享图片
void BridgeVisual_MouseDoubleClick(object sender, MouseButtonEventArgs args)
{??

? ? ?Point?mouseposition?=?args.GetPosition(ViewPort);

? ?MoveCenter(mouseposition);

}

?

?public void MoveCenter(Point mouseposition)
?{
? ? ? PointHitTestParameters pointparams = new PointHitTestParameters(mouseposition);
? ? ? VisualTreeHelper.HitTest(ViewPort, null, HTResultCenter, pointparams);

?}?

?

?private HitTestResultBehavior HTResultCenter(HitTestResult result)
?{
? ? ? RayHitTestResult rayResult = result as RayHitTestResult;
? ? ? if (rayResult != null)
? ? ? {
? ? ? ? ? ?//这就是鼠标点击后在3D中的坐标
? ? ? ? ? ?var hitPoint = rayResult.PointHit;
? ? ? ? ? ?...

? ? ? }

?}?

技术分享图片

?

2.根据相机位置 + 相机的投射方向 = 获取相机在3D上投影的点,camera.Postion就是摄像机在3D世界中的位置了,camera.LookDirection就是摄像机看的方向。那么两者加起来就可以获取这个摄像机投射过后的位置了。?

?

技术分享图片
??////相机位置
??var?cameraPostion?= Camera.Position;
???????????????
??////相机看的方向
??var?lookDirection?= Camera.LookDirection;

??///?获取相机在3D投影的点?
??var?x?=?cameraPostion.X?+?lookDirection.X;
??var?y?=?cameraPostion.Y?+?lookDirection.Y;
??var?z?=?cameraPostion.Z?+?lookDirection.Z;

技术分享图片

?

?

3. 那么利用摄像机投射的位置 - 鼠标双击的位置就可以获取物体应该偏移的量了,WPF中本来就有Transform3D?这个东西进行平移,
此处应用了动画DoubleAnimation,所以代码有点多。

技术分享图片
DoubleAnimation?doubleAnimationX?=?new?DoubleAnimation();
doubleAnimationX.BeginTime?=?new?TimeSpan(0,?0,?0);
doubleAnimationX.Duration?=?TimeSpan.FromMilliseconds(500);
doubleAnimationX.From?= Transform3D.OffsetX;
doubleAnimationX.To?=?x?-?hitPoint.X;

DoubleAnimation?doubleAnimationY?=?new?DoubleAnimation();
doubleAnimationY.BeginTime?=?new?TimeSpan(0,?0,?0);
doubleAnimationY.Duration?=?TimeSpan.FromMilliseconds(500);
doubleAnimationY.From?=?_Transform3D.OffsetY;
doubleAnimationY.To?=?y?-?hitPoint.Y;

DoubleAnimation?doubleAnimationZ?=?new?DoubleAnimation();
doubleAnimationZ.BeginTime?=?new?TimeSpan(0,?0,?0);
doubleAnimationZ.Duration?=?TimeSpan.FromMilliseconds(500);
doubleAnimationZ.From?= Transform3D.OffsetZ;
doubleAnimationZ.To?=?z?-?hitPoint.Z;

Transform3D.BeginAnimation(TranslateTransform3D.OffsetXProperty,?doubleAnimationX);
Transform3D.BeginAnimation(TranslateTransform3D.OffsetYProperty,?doubleAnimationY); ?

技术分享图片

Transform3D.BeginAnimation(TranslateTransform3D.OffsetZProperty,?doubleAnimationZ);??

?

?

4. 最终的效果:

1.平移前:

?技术分享图片

?2.平移后:

?技术分享图片

?

上一篇:Object类 和常用API

下一篇:springcloud config


评论


亲,登录后才可以留言!