我最近開始使用MonoGame,我喜歡圖書館。 不過,我似乎有與繪製Bezier曲線在MonoGame(XNA)中繪製貝塞爾曲線會產生粗糙的線條
,我的代碼產生看起來是這樣的
看不好,沒有結果的一些問題? 線條根本不平滑。
讓我告訴你一些代碼:
//This is what I call to get all points between which to draw.
public static List<Point> computeCurvePoints(int steps)
{
List<Point> curvePoints = new List<Point>();
for (float x = 0; x < 1; x += 1/(float)steps)
{
curvePoints.Add(getBezierPointRecursive(x, pointsQ));
}
return curvePoints;
}
//Calculates a point on the bezier curve based on the timeStep.
private static Point getBezierPointRecursive(float timeStep, Point[] ps)
{
if (ps.Length > 2)
{
List<Point> newPoints = new List<Point>();
for (int x = 0; x < ps.Length-1; x++)
{
newPoints.Add(interpolatedPoint(ps[x], ps[x + 1], timeStep));
}
return getBezierPointRecursive(timeStep, newPoints.ToArray());
}
else
{
return interpolatedPoint(ps[0], ps[1], timeStep);
}
}
//Gets the linearly interpolated point at t between two given points (without manual rounding).
//Bad results!
private static Point interpolatedPoint(Point p1, Point p2, float t)
{
Vector2 roundedVector = (Vector2.Multiply(p2.ToVector2() - p1.ToVector2(), t) + p1.ToVector2());
return new Point((int)roundedVector.X, (int)roundedVector.Y);
}
//Method used to draw a line between two points.
public static void DrawLine(this SpriteBatch spriteBatch, Texture2D pixel, Vector2 begin, Vector2 end, Color color, int width = 1)
{
Rectangle r = new Rectangle((int)begin.X, (int)begin.Y, (int)(end - begin).Length() + width, width);
Vector2 v = Vector2.Normalize(begin - end);
float angle = (float)Math.Acos(Vector2.Dot(v, -Vector2.UnitX));
if (begin.Y > end.Y) angle = MathHelper.TwoPi - angle;
spriteBatch.Draw(pixel, r, null, color, angle, Vector2.Zero, SpriteEffects.None, 0);
}
//DrawLine() is called as following. "pixel" is just a Texture2D with a single black pixel.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
for(int x = 0; x < curvePoints.Count-1; x++)
{
DrawExtenstion.DrawLine(spriteBatch, pixel, curvePoints[x].ToVector2(), curvePoints[x + 1].ToVector2(), Color.Black, 2);
}
spriteBatch.End();
base.Draw(gameTime);
}
我設法通過加入一些人工Math.Round(使線位平滑)調用我的interpolatedPoint方法
//Gets the linearly interpolated point at t between two given points (with manual rounding).
//Better results (but still not good).
private static Point interpolatedPoint(Point p1, Point p2, float t)
{
Vector2 roundedVector = (Vector2.Multiply(p2.ToVector2() - p1.ToVector2(), t) + p1.ToVector2());
return new Point((int)Math.Round(roundedVector.X), (int)Math.Round(roundedVector.Y));
}
這產生了以下結果:
我不得不刪除一張圖片,因爲Stackoverflow不允許我使用兩個以上的鏈接
有什麼方法可以讓這條曲線絕對平滑嗎? 也許DrawLine方法有問題?
在此先感謝。
編輯:
好吧,我設法讓曲線看起來很多做所有的計算與Vector2Ds並且只是在一瞬間將其轉換爲一個點,它需要繪製
更好
它仍然是不完美的,但:/
有什麼聯繫的第二形象嗎?我們可以編輯它。也就是說,很難說出你認爲「完美」應該是什麼。在處理這樣的事情時,永遠不要輪到最後一刻。如果您的繪圖表面可以進行子像素繪製,那麼最後不要進行圓形處理 - 讓畫布處理位置。 (通常,不是繪製各個點,而是跟蹤「當前」和「前一個」點,而是在這些點之間畫線) –
對我來說看起來很好。您可以將您的**編輯**發佈爲下面的答案。 :) – MickyD
你有沒有研究過使用BasicEffect而不是SpriteBatch?我認爲這將是更好的方式去做這種事情。 – craftworkgames