分享

WPF 3D 模型旋转

 xyjackxjw 2013-05-09

WPF 3D 模型旋转

时间:2012-09-20 18:58来源:博客园 作者:yangtam 点击: 513次
WPF 是 Microsoft 在 Framework3.0 中支持的一种技术,它能作出很绚丽的界面,同时它也支持3D的操作。在3D操作主要包括平移(Translate)、旋转(Rotation)、缩放(Scale)。 本文中主要是讨论3D 模型的旋转。对于旋转操作可以采用旋转模型,通过模型的Transform属性来完成;也可以通过第一人称的摄像机通过旋转摄像机来完成旋转
  

  WPF 是 Microsoft 在 Framework3.0 中支持的一种技术,它能作出很绚丽的界面,同时它也支持3D的操作。在3D操作主要包括平移(Translate)、旋转(Rotation)、缩放(Scale)。

  本文中主要是讨论3D 模型的旋转。对于旋转操作可以采用旋转模型,通过模型的Transform属性来完成;也可以通过第一人称的摄像机通过旋转摄像机来完成旋转。当然处于对性能的考虑本文选择第二种方法的方式来旋转模型。

  完成摄像机的旋转需要通过以下几个步骤:

  1. 对于不同的模型,设置摄像机的位置(Position),远焦距(FarPlaneDistance),近焦距(NearPlaneDistance),看的方向(LookDirection),向上的向量(UpDirection)。

  2. 旋转围绕的旋转抽和围绕旋转的中心。

  首先,对于不同的模型放入到世界坐标中摄像机的位置肯定会不同。如何确定摄像机的位置呢?在XNA中XNA框架提供了一个SphereBounding的属性来获得模型的外切圆,从而得到了圆心。然而在WPF中却没有发现SphereBounding的身影。不过仔细想想,Microsoft 不可能在XNA中提供了计算外切圆的方法,在WPF中不可能不提供类似的方法。然后我们仔细寻找,你会发现在MeshGeometry3D有一个Bounds的属性,该属性是返回MesheGeometry3D的边界Rect3D。Rect3D表示一个三维矩形,也就是模型的外切矩形。

  对于一个模型很有可能是由多个ModelVisual3D组成,这就预味着要把这些ModelVisual3D的外切矩形合并,好在在Rect3D中提供了Union方法(MSDN: 已重载。 更新指定的 Rect3D 以反映该 Rect3D 与第二个指定 Rect3D 的联合)。最后通过对三维矩形的Size 和 Location 来计算出矩形的中心。

1 private void UnionRect(ModelVisual3D model, ref Rect3D rect3D)
2         {
3             for (int i = 0; i < model.Children.Count; i++)
4             {
5                 var child = model.Children[i] as ModelVisual3D;
6                 UnionRect(child, ref rect3D);
7
8             }
9             if (model.Content != null)
10                 rect3D.Union(model.Content.Bounds);
11         }

  通过上面获得的中心和矩形的对角线来计算出矩形外切圆的半径。在本例中我们让模型围绕Y轴以自己为中心旋转,所以只需要通过中心点和半径来设置摄像机的Z或者X,通过设置摄像机的X和Z。这样就使得中心点 X,Z在同一个平面中,同时还在同一个圆形中,这样就是的摄像机的旋转围绕着圆点做圆心运动。

public void MeasureModel(ModelVisual3D model)
       {
           var camera = _baseModel.Camera;
           var rect3D = Rect3D.Empty;
           UnionRect(model, ref rect3D);
 
           _center = new Point3D((rect3D.X + rect3D.SizeX / 2), (rect3D.Y + rect3D.SizeY / 2),
                                 (rect3D.Z + rect3D.SizeZ / 2));
 
           double radius = (_center - rect3D.Location).Length;
           Point3D position = _center;
           position.Z += radius * 1.2;
           position.X = position.Z;
           camera.Position = position;
           camera.LookDirection = _center - position;
           camera.NearPlaneDistance = radius / 100;
           camera.FarPlaneDistance = radius * 100;
       }

  设置摄像机的相关属性后,接下来就该是对摄像机做旋转操作了。WPF中旋转提供了两个类AxisAngleRotation3D 和 QuaternionRotation3D。本例中我们选择最常用的AxisAngleRotation3D来完成。在AxisAngleRotation3D提供了CenterX,CenterY,CenterZ这几个属性,用来设置旋转围绕的中心,默认的中心点为(0,0,0),本例中为了实现模型以自己为中心旋转,因此我们需要设置旋转中心。

public void Yaw(bool leftRight, double angleDeltaFactor)
        {
            var camera = _baseModel.Camera;
            var axis = new AxisAngleRotation3D(camera.UpDirection, leftRight ? angleDeltaFactor : -angleDeltaFactor);
            var rt3D = new RotateTransform3D(axis) { CenterX = _center.X, CenterY = _center.Y, CenterZ = _center.Z };
            Matrix3D matrix3D = rt3D.Value;
            Point3D point3D = camera.Position;
            Point3D position = matrix3D.Transform(point3D);
            camera.Position = position;
            camera.LookDirection = camera.LookDirection = _center - position;
        }

源码下载

  本文来自yangtam的博客,原文地址:http://www.cnblogs.com/yangtam/archive/2012/09/20/2696152.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多