3B alanda bir piksel genişliğinde çizgi çizme


10

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:


24

Oluşturma Hatları - Yöntem 1 (İlkeller)

3B alanda basit çizgiler için bunları bir LineListveya LineStripilkel 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 BasicEffectgö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.DrawUserPrimitivesa LineList.

Elbette bunu optimize etmenin birçok yolu vardır, bunların çoğu, VertexBuffertü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 Texture2Dnesne oluşturmak ve onu SpriteBatchdoğru ekran konumunda kullanarak oluşturmak ve Viewport.Project yöntemini kullanarak kolayca bulabilmenizdir .

Gerekli Texture2Dnesneyi ş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ı LineListkullanarak 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:

resim açıklamasını buraya girin


Aynı başlangıç ​​ve bitiş noktasına sahip bir çizgiye ne dersiniz, bu bir nokta üretmez mi? Yoksa sadece görünmez olur mu?
aaaaaaaaaaaa

@eBusiness İyi soru! Sadece denedim ve hiçbir şey yapmıyor.
David Gouveia

@eBusiness Ben sadece bir yol buldum, ama sanırım biraz aptalca. Zaten bütünlük için ekleyeceğim.
David Gouveia

2

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.LineListveya LineStripGPU 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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.