ฉันต้องการวาดเส้นในพื้นที่ 3 มิติที่กว้างเสมอหนึ่งพิกเซลบนหน้าจอไม่ว่ากล้องจะอยู่ไกลแค่ไหน (และเช่นเดียวกันสำหรับจุดเดียวเกินไป)
มีคำแนะนำใด ๆ เกี่ยวกับวิธีที่ฉันสามารถทำได้?
ฉันต้องการวาดเส้นในพื้นที่ 3 มิติที่กว้างเสมอหนึ่งพิกเซลบนหน้าจอไม่ว่ากล้องจะอยู่ไกลแค่ไหน (และเช่นเดียวกันสำหรับจุดเดียวเกินไป)
มีคำแนะนำใด ๆ เกี่ยวกับวิธีที่ฉันสามารถทำได้?
คำตอบ:
เส้นการแสดงผล - วิธีที่ 1 (ดั้งเดิม)
สำหรับเส้นที่เรียบง่ายในพื้นที่ 3D คุณสามารถวาดพวกเขาใช้LineList
หรือLineStrip
ดั้งเดิม นี่คือจำนวนโค้ดขั้นต่ำที่คุณต้องเพิ่มลงในโปรเจ็กต์ XNA ที่ว่างเพื่อให้วาดเส้นจาก (0,0,0) ถึง (0,0, -50) เส้นควรมีความกว้างประมาณเดียวกันไม่ว่าจะวางกล้องไว้ที่ใด
// 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);
ฉันเป็นพื้นสร้างง่ายBasicEffect
ที่จะถือมุมมองและประมาณการของฉันแปลงและผ่านจุดสอง (จัดเก็บตำแหน่งและสี) กับวิธีการที่จะแสดงผลเป็นGraphicsDevice.DrawUserPrimitives
LineList
แน่นอนว่ามีหลายวิธีในการปรับให้เหมาะสมซึ่งส่วนใหญ่เกี่ยวข้องกับการสร้าง a VertexBuffer
เพื่อเก็บจุดยอดทั้งหมดและแบทช์สายให้มากที่สุดเท่าที่เป็นไปได้ในการโทรดึงครั้งเดียว แต่ไม่เกี่ยวข้องกับคำถาม
คะแนนการแสดงผล - วิธีที่ 1 (SpriteBatch)
สำหรับจุดที่วาดภาพนี้ใช้เพื่อจะได้ง่ายโดยใช้สไปรท์จุด แต่พวกเขาจะถูกลบออกจาก XNA 4.0 มีทางเลือกเล็กน้อยว่า วิธีที่ง่ายที่สุดคือการสร้าง 1x1 สีขาวTexture2D
วัตถุและทำให้มันใช้SpriteBatch
ในตำแหน่งที่หน้าจอที่ถูกต้องที่คุณสามารถหาได้ง่ายโดยใช้วิธี Viewport.Project
คุณสามารถสร้างTexture2D
วัตถุที่ต้องการเช่นนี้:
Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new [] { Color.White });
และทำให้มันอยู่ในตำแหน่ง (x, y, z) เช่นนี้:
// 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();
เส้นการแสดงผล - วิธีที่ 2 (SpriteBatch)
หรือคุณยังสามารถวาดเส้นโดยใช้SpriteBatch
โดยใช้เทคนิคการอธิบายไว้ที่นี่ ในกรณีนี้คุณเพียงแค่ต้องค้นหาพิกัดพื้นที่หน้าจอสำหรับปลายทั้งสองด้านของเส้น 3 มิติ (ใช้อีกครั้งViewport.Project
) แล้ววาดเส้นปกติระหว่างพวกเขา
จุดแสดงผล - วิธีที่ 2 (เส้นย่อยที่มีค่าดั้งเดิม)
ในความคิดเห็น eBusiness ยกคำถามต่อไปนี้:
สิ่งที่เกี่ยวกับเส้นที่มีจุดเริ่มต้นและจุดสิ้นสุดเหมือนกันนั่นจะไม่สร้างจุดหรือไม่ หรือว่ามันจะมองไม่เห็น?
ฉันลองและLineList
ใช้งานจุดเริ่มต้นและจุดสิ้นสุดเดียวกันทำให้ไม่มีอะไรถูกดึงออกมา ฉันพบวิธีรอบมัน แต่ฉันจะอธิบายที่นี่เพื่อความสมบูรณ์
เคล็ดลับไม่ได้ใช้จุดเริ่มต้นและจุดสิ้นสุดเดียวกัน แต่เพื่อลากเส้นเล็กจนปรากฏเป็นพิกเซลเดียวเมื่อวาด ดังนั้นเพื่อที่จะเลือกจุดสิ้นสุดที่ถูกต้องฉันแรกคาดการณ์จุดอวกาศโลกในพื้นที่หน้าจอย้ายมันขวาหนึ่งพิกเซลในพื้นที่หน้าจอและในที่สุดก็ฉายมันกลับสู่อวกาศโลก นั่นคือจุดสิ้นสุดของบรรทัดของคุณเพื่อทำให้ดูเหมือนเป็นจุด บางสิ่งเช่นนี้
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);
}
ตามด้วยการเรนเดอร์มันเป็นสายดั้งเดิมดั้งเดิม
สาธิต
นี่คือสิ่งที่ฉันได้วาดเส้นสีขาวในพื้นที่ 3 มิติโดยใช้รายการบรรทัดดั้งเดิมและจุดสีแดงที่ปลายทั้งสองของบรรทัดโดยใช้พื้นผิว 1x1 และ SpriteBatch รหัสที่ใช้นั้นสวยมากที่ฉันเขียนไว้ด้านบน ฉันได้ขยายเข้าไปด้วยดังนั้นคุณจึงสามารถยืนยันได้ว่ามีความกว้างเพียงหนึ่งพิกเซล:
สิ่งนี้ถูกแท็กเป็น XNA ดังนั้นฉันคิดว่านั่นคือสิ่งที่คุณถาม
ถ้าเป็นเช่นนั้นบทความนี้ควรมีประโยชน์สำหรับบรรทัด:
http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.40).aspx
แน่นอนว่าคุณสามารถใช้เมทริกซ์มุมมอง / การฉายภาพของคุณเองแทนที่จะเป็นเมทริกซ์ โดยทั่วไปPrimitiveType.LineList
หรือLineStrip
เป็นวิธีการวาดเส้นที่ระดับ GPU
สำหรับคะแนนคุณไม่สามารถใช้ PrimitiveType.PointList เพื่อดึงคะแนนอีกต่อไปใน XNA 4.0 คุณจะต้องทำสามเหลี่ยมเล็ก ๆ แทน ตัวอย่างนี้ให้พื้นฐานที่ดี:
http://create.msdn.com/education/catalog/sample/primitives_3d
สำหรับ XNA รุ่นก่อนหน้าหากคุณใช้หนึ่งในนั้นคุณสามารถไปข้างหน้าและอ่านส่วนจุดของรุ่น XNA 3.0 ของบทความที่โพสต์ข้างต้น:
http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.30).aspx
หมายเหตุลิงค์มี:
graphics.GraphicsDevice.RenderState.PointSize = 10;
1
เห็นได้ชัดว่าการเปลี่ยนแปลงที่