Mogre学习笔记(三)

  Section 3: Frame Listeners and Windows.Forms Input

FrameListener,是Ogre最有用的部分,下面我们就先来看一下代码:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using MogreFramework;
using Mogre;
using System.Drawing;

namespace Tutorial04
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            try
            {
                MyOgreWindow win = new MyOgreWindow();
                new SceneCreator(win);
                win.Go();
            }
            catch (System.Runtime.InteropServices.SEHException)
            {
                if (OgreException.IsThrown)
                    MessageBox.Show(OgreException.LastException.FullDescription, "An Ogre exception has occurred!");
                else
                    throw;
            }
        }
    }

    class MyOgreWindow : OgreWindow
    {
        const float TRANSLATE = 200;
        const float ROTATE = 0.2f;
        bool mRotating = false;
        Vector3 mTranslation = Vector3.ZERO;
        Point mLastPosition;

        protected override void CreateInputHandler()
        {
            this.Root.FrameStarted += new FrameListener.FrameStartedHandler(FrameStarted);

            this.KeyDown += new KeyEventHandler(KeyDownHandler);
            this.KeyUp += new KeyEventHandler(KeyUpHandler);

            this.MouseDown += new MouseEventHandler(MouseDownHandler);
            this.MouseUp += new MouseEventHandler(MouseUpHandler);
            this.MouseMove += new MouseEventHandler(MouseMoveHandler);

        }

        bool FrameStarted(FrameEvent evt)
        {
            Camera.Position += Camera.Orientation * mTranslation * evt.timeSinceLastFrame;
            return true;
        }

        void KeyDownHandler(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                case Keys.W:
                    mTranslation.z = -TRANSLATE;
                    break;

                case Keys.Down:
                case Keys.S:
                    mTranslation.z = TRANSLATE;
                    break;

                case Keys.Left:
                case Keys.A:
                    mTranslation.x = -TRANSLATE;
                    break;

                case Keys.Right:
                case Keys.D:
                    mTranslation.x = TRANSLATE;
                    break;

                case Keys.PageUp:
                case Keys.Q:
                    mTranslation.y = TRANSLATE;
                    break;

                case Keys.PageDown:
                case Keys.E:
                    mTranslation.y = -TRANSLATE;
                    break;
            }
        }

        void KeyUpHandler(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                case Keys.W:
                case Keys.Down:
                case Keys.S:
                    mTranslation.z = 0;
                    break;

                case Keys.Left:
                case Keys.A:
                case Keys.Right:
                case Keys.D:
                    mTranslation.x = 0;
                    break;

                case Keys.PageUp:
                case Keys.Q:
                case Keys.PageDown:
                case Keys.E:
                    mTranslation.y = 0;
                    break;
            }
        }

        void MouseDownHandler(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Hide();
                mRotating = true;
                mLastPosition = Cursor.Position;
            }
        }

        void MouseUpHandler(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Show();
                mRotating = false;
            }
        }

        void MouseMoveHandler(object sender, MouseEventArgs e)
        {
            if (mRotating)
            {
                float x = mLastPosition.X - Cursor.Position.X;
                float y = mLastPosition.Y - Cursor.Position.Y;

                Camera.Yaw(new Degree(x * ROTATE));
                Camera.Pitch(new Degree(y * ROTATE));

                mLastPosition = Cursor.Position;
            }
        }

    }

    class SceneCreator
    {
        public SceneCreator(OgreWindow win)
        {
            win.SceneCreating += new OgreWindow.SceneEventHandler(SceneCreating);
        }

        void SceneCreating(OgreWindow win)
        {
            win.SceneManager.AmbientLight = new ColourValue(0.25f, 0.25f, 0.25f);

            Entity ent = win.SceneManager.CreateEntity("Ninja", "ninja.mesh");
            win.SceneManager.RootSceneNode.CreateChildSceneNode().AttachObject(ent);

            Light light = win.SceneManager.CreateLight("Light");
            light.Type = Light.LightTypes.LT_POINT;
            light.Position = new Vector3(250, 150, 250);
            light.DiffuseColour = ColourValue.White;
            light.SpecularColour = ColourValue.White;

            win.Camera.Position = new Vector3(0, 200, 400);
            win.Camera.LookAt(ent.BoundingBox.Center);
        }
    }
}

FrameListeners

在Ogre中,我们可以注册一个类在每个Frame呈现之前和之后接收通知,root提供了FrameStarted和FrameEnded事件来处理这些。Ogre的主要循环过程如下:

  1. Root对象发起FrameStarted事件;
  2. Root呈现一个frame;
  3. Root对象发起FrameEnded事件。

这个循环会一直执行,直到其中一个event handlers返回false。FrameEvent对象包括两个变量,但只有timeSinceLastFrame在一个FrameListener中有用。这个变量记录了到上一次FrameStarted或FrameEnded的时间间隔,注意到在frameStarted方法中, FrameEvent.TimeSinceLastFrame指的是到上一次FrameStarted事件的时间,而不是FrameEnded event。

我们写一个简单的FrameStarted函数:

bool FrameStarted(FrameEvent evt)
{
    return true;
}
把它添加到Root.FrameStarted事件中:
this.Root.FrameStarted += new FrameListener.FrameStartedHandler(FrameStarted); 

要使程序响应键盘、鼠标事件,必须添加相应的事件响应代码,见开头的代码部分。需要强调的是,需要在FrameStarted方法中添加如下代码,使响应被呈现:

Camera.Position += Camera.Orientation * mTranslation * evt.timeSinceLastFrame;
按F5运行,就可以用左右上下前后移动摄像头。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值