3B alanda, kameradan ne kadar uzakta olursa olsun, her zaman tam olarak bir piksel genişliğinde bir çizgi çizmek istiyorum. (Ve tek noktalar için de aynı).
Bunu nasıl yapabileceğime dair bir ipucu var mı?
3B alanda, kameradan ne kadar uzakta olursa olsun, her zaman tam olarak bir piksel genişliğinde bir çizgi çizmek istiyorum. (Ve tek noktalar için de aynı).
Bunu nasıl yapabileceğime dair bir ipucu var mı?
Yanıtlar:
Oluşturma Hatları - Yöntem 1 (İlkeller)
3B alanda basit çizgiler için bunları bir LineList
veya LineStrip
ilkel kullanarak çizebilirsiniz . Boş bir XNA projesine eklemeniz gereken minimum kod miktarı (0,0,0) ila (0,0, -50) arasında bir çizgi çizmelidir. Hat, kameranın bulunduğu yere bakılmaksızın kabaca aynı genişliğe sahip gibi görünmelidir.
// Inside your Game class
private BasicEffect basicEffect;
private Vector3 startPoint = new Vector3(0, 0, 0);
private Vector3 endPoint = new Vector3(0, 0, -50);
// Inside your Game.LoadContent method
basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.View = Matrix.CreateLookAt(new Vector3(50, 50, 50), new Vector3(0, 0, 0), Vector3.Up);
basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45f), GraphicsDevice.Viewport.AspectRatio, 1f, 1000f);
// Inside your Game.Draw method
basicEffect.CurrentTechnique.Passes[0].Apply();
var vertices = new[] { new VertexPositionColor(startPoint, Color.White), new VertexPositionColor(endPoint, Color.White) };
GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 1);
Temelde BasicEffect
görünümümü ve projeksiyon dönüşümlerimi tutmak için basit bir basit oluşturdum ve iki köşeyi (depolama konumu ve rengi) GraphicsDevice.DrawUserPrimitives
a LineList
.
Elbette bunu optimize etmenin birçok yolu vardır, bunların çoğu, VertexBuffer
tüm köşeleri depolamak için bir oluşturma oluşturmayı ve mümkün olduğunca çok sayıda satırı tek bir Draw çağrısına toplulamayı içerir, ancak bu soru ile ilgisizdir.
İşleme Noktaları - Yöntem 1 (SpriteBatch)
Noktaları çizmeye gelince, bu nokta sprite kullanarak kolaydı, ancak XNA 4.0'dan çıkarıldı . Yine de birkaç alternatif var. En kolay yol, 1x1 beyaz bir Texture2D
nesne oluşturmak ve onu SpriteBatch
doğru ekran konumunda kullanarak oluşturmak ve Viewport.Project yöntemini kullanarak kolayca bulabilmenizdir .
Gerekli Texture2D
nesneyi şu şekilde oluşturabilirsiniz :
Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new [] { Color.White });
Ve bunu (x, y, z) konumunda şu şekilde render edin:
// Find screen equivalent of 3D location in world
Vector3 worldLocation = new Vector3(0, 0, 50);
Vector3 screenLocation = GraphicsDevice.Viewport.Project(worldLocation, projectionMatrix, viewMatrix, Matrix.Identity);
// Draw our pixel texture there
spriteBatch.Begin();
spriteBatch.Draw(pixel, new Vector2(screenLocation.X, screenLocation.Y), Color.White);
spriteBatch.End();
Oluşturma Satırları - Yöntem 2 (SpriteBatch)
Alternatif olarak, burada açıklanan tekniğiSpriteBatch
kullanarak çizgiler de çizebilirsiniz . Bu durumda, 3B çizginin her iki ucu için (bir kez daha kullanarak ) ekran alanı koordinatını bulmanız ve ardından aralarında düzenli bir çizgi çizmeniz gerekir.Viewport.Project
İşleme Noktaları - Yöntem 2 (İlkel Küçük Çizgi)
Yorumlarda, eBusiness şu soruyu gündeme getirdi:
Aynı başlangıç ve bitiş noktasına sahip bir çizgiye ne dersiniz, bu bir nokta üretmez mi? Yoksa sadece görünmez olur mu?
Ben denedim ve aynı başlangıç ve bitiş noktalarını LineList
kullanarak bir render yapmak hiçbir şey çizilmesiyle sonuçlandı . Yine de bunun etrafında bir yol buldum, bu yüzden burada bütünlük için açıklayacağım.
Hile aynı başlangıç ve bitiş noktalarını kullanmak değil, o kadar küçük bir çizgi çizmektir, çizildiğinde yalnızca bir piksel olarak görünür . Yani, doğru bitiş noktasını seçmek için, ilk, ekran uzaya dünya boşluk noktasını öngörülen doğru bir piksel taşımış ekran alanı içinde ve son olarak geri Dünya uzaya yansıtılan. Nokta gibi görünmesi için çizginizin bitiş noktası budur. Bunun gibi bir şey:
Vector3 GetEndPointForDot(Vector3 start)
{
// Convert start point to screen space
Vector3 screenPoint = GraphicsDevice.Viewport.Project(start, projection, view, Matrix.Identity);
// Screen space is defined in pixels so adding (1,0,0) moves it right one pixel
screenPoint += Vector3.Right;
// Finally unproject it back into world space
return GraphicsDevice.Viewport.Unproject(screenPoint, projection, view, Matrix.Identity);
}
Bunu normal bir çizgi ilkel olarak oluşturarak izler.
gösteri
İşte bir satır listesi ilkel kullanarak bir 3D çizgi beyaz bir çizgi çizim ve 1x1 doku ve SpriteBatch kullanarak çizginin her iki ucunda kırmızı noktalar var. Kullanılan kod hemen hemen yukarıda yazdıklarım. Ayrıca yakınlaştırdım, böylece tam olarak bir piksel genişliğinde olduklarını onaylayabilirsiniz:
Bu XNA olarak etiketlendi, bu yüzden sorduğunuz şey bu?
Öyleyse, bu makale satırlar için yararlı olmalıdır:
http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.40).aspx
Tabii ki onların yerine kendi görünüm / projeksiyon matrislerinizi kullanabilirsiniz. Temel olarak, PrimitiveType.LineList
veya LineStrip
GPU düzeyinde nasıl çizgi çizilir.
Noktalara gelince, artık XNA 4.0'da nokta çizmek için PrimitiveType.PointList'i kullanamazsınız. Bunun yerine çok küçük üçgenler yapmanız gerekir. Bu örnek iyi bir temel sağlar:
http://create.msdn.com/education/catalog/sample/primitives_3d
XNA'nın önceki sürümlerinde, bunlardan birini kullanıyorsanız, yukarıda yayınlanan makalenin XNA 3.0 sürümünün Nokta bölümünü okuyabilirsiniz:
http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.30).aspx
Bağlantının aşağıdakilere sahip olduğuna dikkat edin:
graphics.GraphicsDevice.RenderState.PointSize = 10;
Açıkçası bunu değiştirin 1
.