上節內容中,我們讓物體擁有了最基本的平移和縮放的運動。現在我們來看三大運動之一的旋轉運動。
同上節的知識一樣,要讓物體發生旋轉,只需要在對應的坐標軸上與一個矩陣相乘。這個矩陣的構造方法有三種,分別是:
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) ——
- 前言
- Windows Phone 7開發環境初體驗
- Windows Phone 7 3D開發中使用紋理貼圖
- 在Windows Phone中進行3D開發之一坐標系
- 在Windows Phone中進行3D開發之二攝像機
- 在Windows Phone中進行3D開發之三空間
- 在Windows Phone中進行3D開發之四三角形
- 在Windows Phone中進行3D開發之五平移縮放
- 在Windows Phone中進行3D開發之六旋轉
- 在Windows Phone中進行3D開發之七紋理
- 在Windows Phone中進行3D開發之八光照
- 在Windows Phone中進行3D開發之九模型
- 在Windows Phone中進行3D開發之十組件
- 在Windows Phone中進行3D開發之十一天空
- 在Windows Phone中進行3D開發之十二飛行
- 在Windows Phone中進行3D開發之十三陽光
- 在Windows Phone中進行3D開發之后記(附源碼)