企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
上节内容中,我们让物体拥有了最基本的平移和缩放的运动。现在我们来看三大运动之一的旋转运动。 同上节的知识一样,要让物体发生旋转,只需要在对应的坐标轴上与一个矩阵相乘。这个矩阵的构造方法有三种,分别是: 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](http://blog.csdn.net/caowenbin) ——