3 डी अंतरिक्ष में एक पिक्सेल चौड़ी रेखा खींचना


10

मैं 3 डी स्पेस में एक रेखा खींचना चाहता हूं जो स्क्रीन पर हमेशा एक पिक्सेल चौड़ी होती है, चाहे वह कैमरे से कितनी भी दूर हो। (और एकल बिंदुओं के लिए भी यही)।

कोई संकेत है कि मैं ऐसा कैसे कर सकता हूं?

जवाबों:


24

रेंडरिंग लाइन्स - विधि 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 बनावट और स्प्राइटबैच का उपयोग करके लाइन के दोनों सिरों पर लाल डॉट्स। उपयोग किया गया कोड बहुत ज्यादा है जो मैंने ऊपर लिखा है। मैंने भी ज़ूम किया है ताकि आप पुष्टि कर सकें कि वे एक पिक्सेल चौड़े हैं:

यहाँ छवि विवरण दर्ज करें


एक ही शुरुआत और अंत बिंदु के साथ एक पंक्ति के बारे में क्या, जो एक बिंदु का उत्पादन नहीं करेगा? या यह केवल अदृश्य होगा?
आआआआआआआआआआआ आआआआआआना

@eBusiness अच्छा सवाल! मैं सिर्फ यह एक कोशिश की, और वास्तव में यह कुछ भी प्रस्तुत नहीं करता है।
डेविड गॉविया

@eBusiness मुझे अभी एक रास्ता मिला है, लेकिन मुझे लगता है कि यह थोड़ा मूर्खतापूर्ण है। मैं इसे पूर्णता के लिए वैसे भी जोड़ दूँगा।
डेविड गौवेया

2

इसे 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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.