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

来源:互联网 发布:个人能在淘宝开店吗 编辑:程序博客网 时间:2024/05/17 09:17

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

 

       同上节的知识一样,要让物体发生旋转,只需要在对应的坐标轴上与一个矩阵相乘。这个矩阵的构造方法有三种,分别是:

              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 ——



原创粉丝点击