使用這段代碼,可以對我們將使用的任何矩陣求逆。
關(guān)于Matrix類的內(nèi)容就是這些,現(xiàn)在這個類對于2D和3D應(yīng)用程序都適用。接下來就實際使用這個類。
8.5.7 對精靈執(zhí)行矩陣操作
創(chuàng)建一個新的游戲狀態(tài)MatrixTestState。這個狀態(tài)將繪制一個精靈,并對該精靈應(yīng)用各種矩陣。下面是繪制精靈的代碼,你應(yīng)該已經(jīng)很熟悉這段代碼了。
class MatrixTestState : IGameObject
{
Sprite _faceSprite = new Sprite();
Renderer _renderer = new Renderer();
public MatrixTestState(TextureManager textureManager)
{
_faceSprite.Texture = textureManager.Get("face");
Gl.glEnable(Gl.GL_TEXTURE_2D);
}
public void Render()
{
Gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
_renderer.DrawSprite(_faceSprite);
_renderer.Render();
}
public void Update(double elapsedTime)
{
}
}
代碼中使用了前面章節(jié)中用到的臉部精靈。矩陣將在MatrixTestState構(gòu)造函數(shù)中應(yīng)用到精靈上。
Matrix m = new Matrix();
m.SetRotate(new Vector(0, 0, 1), Math.PI/5);
for (int i = 0; i < _faceSprite.VertexPositions.Length; i++ )
{
_faceSprite.VertexPositions[i] *= m;
}
運行代碼,可以注意到臉部已經(jīng)被旋轉(zhuǎn)過了。旋轉(zhuǎn)是沿著Z軸(0,0,1)執(zhí)行的,這是從屏幕內(nèi)部指向外部的軸。把臉部精靈想象成屏幕上的一張紙。為了進(jìn)行旋轉(zhuǎn),你在紙上按了一個圖釘,使其附著到屏幕上了。圖釘就代表Z軸。旋轉(zhuǎn)紙精靈就是在沿著該軸旋轉(zhuǎn)。對于正射投影中的2D對象,Y軸和Z軸對于旋轉(zhuǎn)來說沒有什么用處,但是在3D游戲中就不一樣了。任何一個歸一化的軸都可以用于旋轉(zhuǎn)對象,不只是X、Y和Z這3個主軸。
在代碼示例中,旋轉(zhuǎn)量以弧度Math.PI/5給出,這個值等于36°。旋轉(zhuǎn)矩陣將被應(yīng)用到組成精靈的每個頂點。我們現(xiàn)在已經(jīng)使用了一個稍微旋轉(zhuǎn)了精靈的矩陣。接下來就添加一個縮放精靈的矩陣。通過使用矩陣乘法,縮放矩陣將與旋轉(zhuǎn)矩陣結(jié)合起來。修改構(gòu)造函數(shù)中的已有代碼,使其如下所示。
Matrix m = new Matrix();
m.SetRotate(new Vector(0, 0, 1),Math.PI/5);
Matrix mScale = new Matrix();
mScale.SetScale(new Vector(2.0, 2.0, 0.0));
m *= mScale;
for (int i = 0; i < _faceSprite.VertexPositions.Length; i++ )
{
_faceSprite.VertexPositions[i] *= m;
}
這段代碼創(chuàng)建的縮放矩陣將對象在X軸和Y軸上放大一倍。這個矩陣和旋轉(zhuǎn)矩陣通過矩陣乘法結(jié)合到一起,然后把結(jié)果賦值給矩陣m。然后這個合并后的矩陣m被應(yīng)用到臉部精靈,以縮放和旋轉(zhuǎn)該精靈。矩陣乘法的順序很重要:將矩陣a和矩陣b相乘的結(jié)果不一定與將矩陣b和矩陣a相乘的結(jié)果相同。嘗試采用不同的矩陣,以熟悉它們之間相互組合后可以得到什么樣的結(jié)果。
最后的代碼段將演示逆矩陣。逆矩陣會逆轉(zhuǎn)一個矩陣操作。如果將旋轉(zhuǎn)-縮放矩陣乘以其逆矩陣,結(jié)果將是一個單位矩陣。對精靈應(yīng)用單位矩陣時,不會產(chǎn)生任何效果。
Matrix m = new Matrix();
m.SetRotate(new Vector(0, 0, 1),Math.PI/5);
Matrix mScale = new Matrix();
mScale.SetScale(new Vector(2.0, 2.0, 2.0));
m *= mScale;
Vector scale = m.GetScale();
m *= m.Inverse();
for (int i = 0; i < _faceSprite.VertexPositions.Length; i++ )
{
_faceSprite.VertexPositions[i] *= m;
}
你還可以嘗試平移矩陣,并試著以不同的順序組合矩陣,看看會得到什么效果。