[英]XNA - matrix equivalent to SpriteBatch.Draw transformations?
說我有這個界面:
interface Drawable {
Vector2 DrawPosition { get; }
Texture2D Texture { get; }
float Rotation { get; }
Vector2 Origin { get; }
Vector2 Scale { get; }
bool FlipHorizontally { get; }
}
在擴展Microsoft.Xna.Framework.Game的類中,我重寫Draw(GameTime),並且此代碼在其中:
Drawable d = ...;
spriteBatch.Begin();
spriteBatch.Draw(d.Texture, d.DrawPosition, new Rectangle(0, 0, d.Texture.Width, d.Texture.Height), Color.White, d.Rotation, d.Origin, d.Scale, d.FlipHorizontally ? SpriteEffects.FlipHorizontally : SpriteEffects.None, 0);
spriteBatch.End();
這將使用SpriteBatch.Draw(Texture2D紋理,Vector2位置,Nullable sourceRectangle,顏色,浮點旋轉,Vector2原點,Vector2比例,SpriteEffects效果,浮點layerDepth)重載。
假設我有一組頂點,該頂點對d.Texture返回的圖像進行了粗略的輪廓繪制(也就是說,如果我在Microsoft Paint中打開圖像並用鉛筆繪制該頂點集中的每個點,則該頂點將非常適合)。 如果我想繪制這些點以便使用GraphicsDevice.DrawUserPrimitives()遍歷紋理,是否有一種方法可以僅使用矩陣來變換頂點? 關鍵是它只能使用矩陣,而我沒有其他選擇可以繪制,因為我實際上還需要將變換后的頂點用於其他事物。 我已經嘗試過類似的東西
Matrix.CreateTranslation(new Vector3(-d.Origin, 0))
* Matrix.CreateScale(new Vector3(d.Scale, 0))
* Matrix.CreateRotationZ(d.Rotation)
* Matrix.CreateTranslation(new Vector3(d.DrawPosition, 0)));
但是失敗很困難。 有解決這個問題的方法嗎?
您的矩陣代碼看起來很適合World矩陣(將模型放置在世界空間中)。 所以我猜這是其中之一:
您的基元在模型空間中的位置錯誤。 Sprite批處理創建單個多邊形,其中(0,0)是Sprite的左上角,而({texture width},{texture height})是右下角。 您的基本體必須具有相同的大小和位置。
您的投影矩陣是錯誤的。 看到這個答案 。 請注意, SpriteBatch
使用翻轉的(客戶空間)坐標系。
您的背面剔除模式是錯誤的(不考慮翻轉坐標系)。
您遇到了深度緩沖問題(您需要在遠近平面內繪制,並且是否被任何東西淘汰掉了?)
如果仍然有問題,請從DirectX SDK中獲取PIX並使用它來標識您的游戲實際繪制的內容。
噢,天哪,我很抱歉。 我只是意識到不匹配的全部原因是因為我弄錯了頂點! 好吧,我想如果你們在做同一件事上需要幫助,這是我的最終版本:
abstract class Drawable
{
public abstract Vector2 DrawPosition { get; }
public abstract Texture2D Texture { get; }
public abstract float Rotation { get; }
public abstract Vector2 Origin { get; }
public abstract Vector2 Scale { get; }
public abstract bool FlipHorizontally { get; }
public abstract Vector2[] Vertices { get; }
public Matrix TransformationMatrix
{
get
{
return Matrix.CreateTranslation(-new Vector3(Texture.Width * Scale.X / 2, 0, 0))
* Matrix.CreateScale(new Vector3(FlipHorizontally ? -1 : 1, 1, 1))
* Matrix.CreateTranslation(new Vector3(Texture.Width * Scale.X / 2, 0, 0))
* Matrix.CreateTranslation(-new Vector3(Origin, 0))
* Matrix.CreateScale(new Vector3(Scale, 0))
* Matrix.CreateRotationZ(Rotation)
* Matrix.CreateTranslation(new Vector3(DrawPosition, 0));
}
}
}
class Camera
{
private readonly Viewport viewport;
public Matrix GetViewMatrix()
{
return Matrix.CreateScale(1, -1, 1) * Matrix.CreateTranslation(0, viewport.Height, 0);
}
public Vector2 MouseToWorld(int x, int y)
{
return Vector2.Transform(new Vector2(x, y), Matrix.CreateScale(1, -1, 1) * Matrix.CreateTranslation(0, viewport.Height, 0));
}
}
class Game1 : Microsoft.Xna.Framework.Game
{
private Drawable avatar;
private Camera camera;
...
protected override void Initialize() {
avatar = ...;
camera = new Camera(graphics.GraphicsDevice.Viewport);
basicEffect = new BasicEffect(graphics.GraphicsDevice);
basicEffect.VertexColorEnabled = true;
basicEffect.Projection = Matrix.CreateOrthographicOffCenter(0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height, 0, 0, 1);
base.Initialize();
}
...
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, camera.GetViewMatrix());
spriteBatch.Draw(avatar.Texture, avatar.DrawPosition, new Rectangle(0, 0, avatar.Texture.Width, avatar.Texture.Height), Color.White, avatar.Rotation, avatar.Origin, avatar.Scale, avatar.FlipHorizontally ? SpriteEffects.FlipHorizontally : SpriteEffects.None, 0);
spriteBatch.End();
basicEffect.CurrentTechnique.Passes[0].Apply();
VertexPositionColor[] vertices = new VertexPositionColor[avatar.Vertices.Length + 1];
Matrix m = MakeAffineTransform(avatar);
for (int i = 0; i < avatar.Vertices.Length; i++)
{
vertices[i] = new VertexPositionColor(Vector3.Transform(new Vector3(Vector2.Transform(avatar.Vertices[i], m), 0), camera.GetViewMatrix()), Color.Black);
Console.WriteLine(vertices[i]);
}
vertices[vertices.Length - 1] = vertices[0];
graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, vertices, 0, vertices.Length - 1);
base.Draw(gameTime);
}
...
}
它工作得很漂亮! 實際上,這會翻轉原點,使其位於左下角,同時也會翻轉y軸,以使增加的值向上移動而減少的值向下移動。 相機可能是很好的基礎,並且可以輕松更新(例如,如果要使其跟隨屏幕上的某物),以便可以向其傳遞世界坐標(原點位於左下角),並且ll返回屏幕坐標。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.