您的位置:首页 > 其它

在Windows Phone中进行3D开发之六旋转

2011-11-17 18:30 218 查看
上节内容中,我们让物体拥有了最基本的平移和缩放的运动。现在我们来看三大运动之一的旋转运动。

同上节的知识一样,要让物体发生旋转,只需要在对应的坐标轴上与一个矩阵相乘。这个矩阵的构造方法有三种,分别是:
Matrix CreateRotationX(float radians);
Matrix CreateRotationY(floatradians);
Matrix CreateRotationZ(float radians);
代表在x、y、z三个坐标轴上的旋转角度,其中radians是弧度表示,如果想使用我们熟悉的角度的话,可以使用MathHelper.ToRadians(10)进行转换。
除了沿着坐标轴旋转以外,还有一种是采用飞行器的偏航、翻滚、俯仰表示方式进行的旋转,使用的矩阵构造方法是:
Matrix CreateFromYawPitchRoll(float yaw, float pitch, float roll);
有兴趣的朋友可以自行学习。

还是沿用上节课我们建好的XNA项目,在VS2010中打开该项目。打开Game1.cs文件,我们来修改Game1类。为其添加成员变量,代表旋转矩阵:
Matrix rotateMatrix=Matrix.Identity;
同时为了便于观察,我们将上节使用的scaleMatrix取值为0.5倍的缩放:
Matrixs caleMatrix = Matrix.CreateScale(0.5f);
然后在Draw()方法中修改basicEffect对象的World属性:
basicEffect.World= scaleMatrix * translateMatrix * rotateMatrix;
在Update()方法中去掉对scaleMatrix的变化并增加对rotateMatrix的处理:
//scaleMatrix= Matrix.CreateScale(0.9f);
rotateMatrix*= Matrix.CreateRotationZ(MathHelper.ToRadians(10));
也即每次点击屏幕产生10度的旋转。

运行程序,观察旋转的结果。然后尝试将Draw()中的
basicEffect.World= scaleMatrix * translateMatrix * rotateMatrix;
改成
basicEffect.World= scaleMatrix * rotateMatrix * translateMatrix;
来观察对旋转的影响。从中可以看出,前者是先沿着物体的x转产生了平移,然后再按平移后所在的位置的z轴进行旋转,产生了像螺线一样的运动。而后者是先沿z轴进行了旋转,再沿x轴进行平移,产生了一边向屏幕右侧平移同时绕自身z轴旋转的效果。因此,在实际项目中要小心处理矩阵运算。

另外,也可以修改代码,观察沿x、y轴旋转的情况。

当我们让三角形绕y轴旋转的时候,会发现一个奇怪的现象,随着物体的旋转,当物体的背面朝向我们时,我们就看不到它了。其实这是渲染引擎的优化设置,因为对于物体的背面,实际上是不进行渲染的,也就是常说的背面消隐,有需要关注的朋友可以查找相关的资料,在这里要想取消背面消隐选项,只需要修改一下GraphicsDevice的栅格化参数,即在Draw()方法中加入下面的代码:
GraphicsDevice.Clear(Color.CornflowerBlue);
RasterizerState rasterizerState = new RasterizerState();
rasterizerState.CullMode = CullMode.None;
GraphicsDevice.RasterizerState = rasterizerState;

附本节Game1类的完整源码:

public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        Camera camera;
        Matrix world = Matrix.Identity;
        BasicEffect basicEffect;
        VertexPositionColor[] triangle;
        Matrix translateMatrix=Matrix.Identity;
        Matrix scaleMatrix = Matrix.CreateScale(0.5f);
        Matrix rotateMatrix = Matrix.Identity;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // Frame rate is 30 fps by default for Windows Phone.
            TargetElapsedTime = TimeSpan.FromTicks(333333);

            // Extend battery life under lock.
            InactiveSleepTime = TimeSpan.FromSeconds(1);
            graphics.IsFullScreen = true;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            camera = new Camera(this, new Vector3(0, 0, 5), Vector3.Zero, Vector3.Up, MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 1.0f, 50.0f);
            Components.Add(camera);
            basicEffect = new BasicEffect(GraphicsDevice);
            triangle = new VertexPositionColor[]{
                new VertexPositionColor(new Vector3(0, 1, 0), Color.Red),
                new VertexPositionColor(new Vector3(1, -1, 0), Color.Green),
                new VertexPositionColor(new Vector3(-1,-1, 0), Color.Blue)
            };
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            TouchPanel.EnabledGestures = GestureType.Tap;
            if (TouchPanel.IsGestureAvailable)
            {
                GestureSample gestureSample = TouchPanel.ReadGesture();
                if (gestureSample.GestureType == GestureType.Tap)
                {
                    translateMatrix *= Matrix.CreateTranslation(0.3f, 0, 0); 
                    //scaleMatrix = Matrix.CreateScale(0.9f);
                    rotateMatrix *= Matrix.CreateRotationY(MathHelper.ToRadians(10));
                }
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            RasterizerState rasterizerState = new RasterizerState();
            rasterizerState.CullMode = CullMode.None;
            GraphicsDevice.RasterizerState = rasterizerState;

            basicEffect.World = scaleMatrix * translateMatrix * rotateMatrix;
            basicEffect.View = camera.view;
            basicEffect.Projection = camera.projection;
            
            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                pass.Apply();
                GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, triangle, 0, 1);
            }

            base.Draw(gameTime);
        }
    }


——欢迎转载,请注明出处 http://blog.csdn.net/caowenbin ——
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: