मैं 3 डी स्पेस में एक रेखा खींचना चाहता हूं जो स्क्रीन पर हमेशा एक पिक्सेल चौड़ी होती है, चाहे वह कैमरे से कितनी भी दूर हो। (और एकल बिंदुओं के लिए भी यही)।
कोई संकेत है कि मैं ऐसा कैसे कर सकता हूं?
मैं 3 डी स्पेस में एक रेखा खींचना चाहता हूं जो स्क्रीन पर हमेशा एक पिक्सेल चौड़ी होती है, चाहे वह कैमरे से कितनी भी दूर हो। (और एकल बिंदुओं के लिए भी यही)।
कोई संकेत है कि मैं ऐसा कैसे कर सकता हूं?
जवाबों:
रेंडरिंग लाइन्स - विधि 1 (आदिम)
3 डी अंतरिक्ष में सरल लाइनों के लिए आप एक 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
।
बेशक, इसे अनुकूलित करने के कई तरीके हैं, जिनमें से अधिकांश में VertexBuffer
सभी कोने को स्टोर करना शामिल है , और एक ही ड्रॉ कॉल में जितनी संभव हो उतने पंक्तियों को बैचना है लेकिन यह सवाल के लिए अप्रासंगिक है।
रेंडरिंग पॉइंट्स - विधि 1 (स्प्राइटबैच)
ड्राइंग पॉइंट्स के लिए, यह पॉइंट स्प्राइट्स का उपयोग करके आसान हुआ करता था लेकिन उन्हें 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
का उपयोग करके लाइनें भी खींच सकते हैं । इस मामले में आपको बस 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 बनावट और स्प्राइटबैच का उपयोग करके लाइन के दोनों सिरों पर लाल डॉट्स। उपयोग किया गया कोड बहुत ज्यादा है जो मैंने ऊपर लिखा है। मैंने भी ज़ूम किया है ताकि आप पुष्टि कर सकें कि वे एक पिक्सेल चौड़े हैं:
इसे XNA के रूप में चिह्नित किया गया है इसलिए मैं मान रहा हूं कि आप किस बारे में पूछ रहे हैं?
यदि हां, तो यह लेख लाइनों के लिए उपयोगी होना चाहिए:
http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.40).aspx
बेशक आप उनके बजाय अपने स्वयं के दृश्य / प्रक्षेपण मैट्रिस का उपयोग कर सकते हैं। मूल रूप से, PrimitiveType.LineList
या LineStrip
जीपीयू स्तर पर लाइनों को कैसे खींचना है।
बिंदुओं के लिए, अब आप XNA 4.0 में अंक बनाने के लिए PrimitiveType.PointList का उपयोग नहीं कर सकते। इसके बजाय आपको बहुत छोटे त्रिकोण बनाने होंगे। यह नमूना एक अच्छी आधार रेखा प्रदान करता है:
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
।