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

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

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

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值