前几天有点感冒,有点码不动代码。本来计划的鼠标控制也只是写了一半:不是因为编程问题,是因为用户体验问题。具体的稍后说,先更正一下前篇中出现的问题,关于正交投影,我们默认使用的是左手坐标系,那么之前那张图就应该是这样(上篇文章里的这图已经在稍早的时候改过了):
图片
       也就是观察者坐标系的Z轴标记反了。而矩阵公式中所谓的“相对于某轴旋转X度”,经过我的实验发现应该是:正面对此轴(轴投影是个点,而不是叉,绕轴逆时针旋转X度。(看起来就是原坐标系顺时针旋转了X度)而投影的区域我们设定为z负半轴区域。
       所以说,控制视角的一共有六个参数,视点坐标(x,y,z),和视点角度(x,y,z)。其实有三种视角模式:以坐标原点为参考点进行旋转平移、以当前视点,以及对于某个实体的追随视角。本来,以当前视点为参考点的变换涉及之前那个变换矩阵的逆矩阵,这个矩阵相~~当~~复杂。不过matlab倒是很快就算出来了——嗯,我也第一次编程时还用matlab来辅助……试了几次,感觉电脑并不卡,说明这些数学计算对于计算机还是很轻松的。所以说鼠标控制的性质还是用户体验占较大成分,于是我就准备留着以后整体优化时再弄了……下图就是之前那个变换矩阵的逆矩阵:
图片
╮(╯_╰)╭

现在主界面的样子:
图片

       实体管理子窗口还会有大的改动,因为还没做和数据库的链接,所以只是在程序里预设了两个实体来测试,以后和数据库(ADO.NET)连上后,无论实体数据还是运动数据都会和数据库绑定就是了。 
       所以这几天除了各种DEBUG以外,完成的两个功能就是:Timer的精确计时,以及实体运动模拟的基本测试,所谓实体就是上面两个黑点,本来我还想画漂亮点的,不过……嘛,后期优化的时候再说~~

       C#可视化控件里的那个Timer实际是System.Windows.Forms.Timer,直接使用时差不多只能实现精确到秒的计时——Interval设置小于17就会出现明显误差(慢好多= =)。我很喜欢看秒表上毫秒飞跑,又想精确计时……所以我也就自作孽不可活地上网开始找C#精确计时的解决方案。源地址忘保存了……不过源程序做点有点花哨……我依葫芦画瓢把其中精确计时的部分移植到了一个空工程上,顺利跑起来后再移植到Digital Void上的,简单地说,它多建了一个”项目“,也就是拿出一个线程来辅佐计时,首先在主项目(Form)上定义一些变量:
        public DateTime StartTime;
        public TimeSpan TimePauseSpan;
        public DateTime SpanDateTime;
        public TimeSpan Span;
        public TimeSpan LastTimeSpan;
        public TimeSpan TotalSpan;
        public bool IsPaused = false;
        DateTime和TimeSpan都在定义在System中的,直接拿来用就行。然后在Form的构造函数里写上:timer.Enabled = false;timer.Interval = 1;在timer_Tick事件里的相关代码则是:

        private void timer_Tick(object sender, EventArgs e)
        {
            Span = (DateTime.Now - StartTime).Add(this.TimePauseSpan);       //Use system time to calcuate the TimeSpan
            SpanDateTime = new DateTime(Span.Ticks);
            this.TimeLabel.Text = SpanDateTime.ToString("HH:mm:ss.ff");
        }

         另一方面,另外添加的ConsoleTimer项目是一个控制台项目,里面Program.cs里的主函数是:

        static void Main(string[] args)
        {
            MainForm MainForm = new MainForm();
            PlayControl PC = new PlayControl(MainForm);  //这两句是我自己写的,用于和主窗体建立联系,与计时无关
            PC.PlayPress(); //这是开始计时的触发函数。
            Thread.Sleep(1000);
            PC.PlayPress();
            Thread.Sleep(1000);
            PC.StopPress();
        } 
        基本源码就是这样,整体上应该是利用了线程睡眠以及系统时间来实现精确计时的。更进一步我也不是很懂,所以贴上来供有兴趣的朋友讨论~~


       运动模拟部分,基本就是积分数值解的原理,在DEBUG掉我的几个脑残手误后,基本有个样子了,不过不知是积分步长太长还是数据类型精度不够(一直用的是float),本来设计的一个稳定双星,结果轨道还是发散了,以后优化的时候再看情况吧,不行就全改成double……Orz
先上几个图好了:
 
图片

图片

(后加,我后来把积分步长缩小到了千分之一,发散问题已经明显好转了~)
显示轨迹的功能将会在链接上数据库后加上~~


总之整个计划还是比较顺利的,清明节再加把油,之后就不能像现在空闲时间全拿来码代码了……还得准备英语和考研呐Orz