MDX之平移与旋转(2)

简介

======================================================

昨天我发过了平移的一篇文章,就有人说都有现存的算法存在了,不错,我要提醒一下,我并不是什么技术高超的学者,

或者说是某某研究员,那么我的算法怎么来呢,有人说过天下文章一大抄,看你会抄不会抄,不知道大家有没有去过那些

论文网站,有没有去那里找过什么论文,反正我是常去的,你去了你就会发现,他们的那些很多算法也是别人已经做过,

已经写过的。

 

我发在这里也只是想起到一种提醒的作用,要说让我自己想一个什么高深的算法,我自认现在还没有那个水平。

======================================================

 

 首先,在MDX中要通过鼠标的旋转就知道,鼠标这时的移动并不是在一个平面内移动,而是在一个半球内移动的。

                                                    

就象上图中的从A到B点是按照圆的轨迹在移动,而不是按直线由A到B的。


旋转之所有叫旋转那就要有旋转轴和旋转角,旋转轴也就是平面OAB的法向量,平面的法向量有公式可以求的,旋转角

一样也有公式可以求:

n=OA×OB

α=ACOS((OA*OB)/(|OA|*|OB|))

在程序中旋转角(α)可以设置为2倍,这样如果用鼠标点击视图的左中边缘,然后拖动至视图的右中边缘,则可实现

模型以y 轴为旋转轴的360旋转,也就是一周。

 

现在的问题就成了求A,B两点坐标的问题了,那么这两点的坐标怎么样的确定呢,注意有两种情况:


还 有一个问题就是R的大小,R一般会设置成为窗口宽度的一半;

 

到此要解决的问题除了一个问题也就差不多都解决了,那个问题下面再说,我将代码copy到下面我在一句句说。。

 

 1                     float radius = (this.Width / 2> (this.Height / 2? (this.Width / 2) : (this.Height / 2);
 2                     Vector3 preVector = new Vector3();      // 前一次鼠标与中心点的向量
 3                     preVector.X = _posLast.X - radius;       //A点坐标
 4                     preVector.Y = _posLast.Y - radius;
 5                     float square = radius * radius - preVector.X * preVector.X - preVector.Y * preVector.Y;
 6                     if (square <= 0)                        //前面说到的两tk
 7                     {
 8                         square = 0;
 9                         preVector.Z = 0;
10 
11                         preVector.X = preVector.X / preVector.Length();
12                         preVector.Y = preVector.Y / preVector.Length();
13                     }
14                     else
15                     {
16                         preVector.Z = (float)Math.Sqrt(square);
17 
18                         preVector.X = preVector.X / radius;     // 单位化
19                         preVector.Y = preVector.Y / radius;
20                         preVector.Z = preVector.Z / radius;
21                     }
22 
23                     Vector3 curVector = new Vector3();      // 现在鼠标与中心点的向量
24                     curVector.X = e.X - radius;                   //A点坐标
25                     curVector.Y = e.Y - radius;
26                     square = radius * radius - curVector.X * curVector.X - curVector.Y * curVector.Y;
27                     if (square <= 0)
28                     {
29                         square = 0;
30                         curVector.Z = 0;
31 
32                         curVector.X = preVector.X / curVector.Length();
33                         curVector.Y = curVector.Y / curVector.Length();
34                     }
35                     else
36                     {
37                         curVector.Z = (float)Math.Sqrt(square);
38 
39                         curVector.X = curVector.X / radius;
40                         curVector.Y = curVector.Y / radius;
41                         curVector.Z = curVector.Z / radius;
42                     }
43 
44                     if (preVector == curVector)
45                         return;
46 
47                     Vector3 crossVector = Vector3.Cross(preVector, curVector);
48                     float alpha = (float)Math.Acos(Vector3.Dot(preVector, curVector) / (preVector.Length() * curVector.Length()));
49 
50                     _matrixRotation.Multiply(Matrix.RotationAxis(crossVector, alpha * 2));      

 

这里我将最后的三句拿出来:

44-47:为什么要有这两句?这个可是为个算法里面的一个比较关键的地方, 这个算法有一点小问题就是当OA与OB

也就是preVector与curVector相隔非常小甚至相等的时候,大家想想会发生什么事情,想想Vector3.Cross()这个函数

是干什么的,如果上面两者相等会发生什么,这个就是我在做的时候就找了好久才找到的这个缺陷 ,开始我还以为是

算法本身有问题,就想了很多别的算法,绕了一大圈才找到这个。

 

48:求两者之间的角度

 

50:旋转2倍的角度(个人习惯),这里也要注意是每一次的旋转都要累加到一起来,matrixRotation就起到了累加器的

作用,并且还要是右乘上现在的旋转量,不是左乘

 

好了,现在这个也就说完了,其实也比较的简单,其实技术就象我们老师说的一样,技术就是一张纸,在捅破之前非常

神秘,捅破之后就一钱不值了。

posted @ 2008-08-23 19:36  connoryan  阅读(1979)  评论(2编辑  收藏  举报