2012-09-28 18 views
18

ड्राइंग मैं एक प्रोग्राम है जो, मूल रूप से, (एक "छोड़ कैनवास" में) कई छोटे त्रिभुजों में एक ज्यामितीय आकार में कटौती तैयार की है, त्रिकोण के गुच्छा के लिए कुछ सरल गणितीय परिवर्तन लागू होती है और में उन्हें redraws उनकी नई विन्यास। नीचे स्क्रीन कैप्चर देखें।क्यूटी/C++: कुशलतापूर्वक

screen cap 1

इन त्रिकोण आकर्षित करने के लिए में, मैं QPainter::drawPolygon का उपयोग करें। दाईं तरफ प्रत्येक त्रिकोण बाईं ओर एक त्रिकोण से मेल खाता है, इसलिए मुझे पता है कि मैं इसे आकर्षित करने के लिए किस रंग का उपयोग करना चाहता हूं।

अभी तक, ठीक है। यहां तक ​​कि अगर मैं इस से अधिक त्रिकोण खींचता हूं (जब मैं आकार को काटने के लिए बहुत छोटे त्रिकोण का उपयोग करता हूं), यह पर्याप्त तेज़ है।

मैं अपने कार्यक्रम के लिए एक सुविधा जोड़ी है: मैं एक के बजाय चित्र सादा त्रिकोण से निकाला त्रिकोण आकर्षित कर सकते हैं: स्क्रीन कब्जे के बाद देखते हैं।

enter image description here

समस्या यह है कि जिस तरह से मैं यह कर भी धीमी है। यहाँ कैसे मैं यह कर दिया गया है:

  1. मैं सभी त्रिकोण
  2. प्रत्येक त्रिकोण के लिए के माध्यम से चलाने के लिए, मैं प्रत्येक पिक्सेल कि प्रदर्शित किया जाएगा के निर्देशांक की गणना।
  3. इन पिक्सल में से हर एक के लिए, मैं चित्र पर इसी पिक्सेल के निर्देशांक (यह एक आसान गणितीय प्रक्रिया है) की गणना, और मुझे लगता है कि पिक्सेल के रंग को पुनः प्राप्त।
  4. मैं QPainter::setPen(QColor) और QPainter::drawPoint(QPoint) का उपयोग पिक्सेल आकर्षित करने के लिए।

मैं क्यूटी में प्रोग्रामिंग के लिए नया हूं और मुझे ग्राफिक्स के बारे में कुछ नहीं पता है, इसलिए मैं यही कर सकता हूं। समस्या यह है कि यह "अस्वीकार्य" बहुत धीमी है (प्रत्येक कैनवास के paintEvent सादे त्रिकोण के मामले में 0.01 के मुकाबले 0.15s लेता है)।

मैं समझने के लिए क्या हो रहा है की कोशिश करने के लिए एक प्रोफाइलर भाग गया, मैंने देखा है कि में कैनवास विजेट के paintEvent, समय की

  1. 58% में समय की QPainter::drawPoint
  2. 27% खर्च किया जाता है खर्च किया जाता है QPainter::setPen

में ऐसा लगता है कि QPainter::drawPoint अभी तक बहुत जटिल और धीमी है: मैं बस यह किसी दिए गए रंग का एक पिक्सेल प्रिंट करना चाहते हैं, बस इतना ही।

मैं अपने समस्या का समाधान मिल गया है हो सकता है: स्टोर एक QImage कि पूरी बात मैं अपने कैनवास प्रदर्शित करना चाहते हैं का प्रतिनिधित्व करता है, और पिक्सेल द्वारा मेरी paintEvent पिक्सेल में यह पूरी तरह से परिभाषित करते हैं (मेरी कैनवास विजेट के एक सदस्य चर के रूप में), और फिर के साथ अपने paintEvent के अंत में इसे एक बार खींचें। मुझे एक संकेत है कि यह बहुत तेज होगा। लेकिन इससे पहले कि मैं फिर से अपना कोड फिर से लिखूं, मैं जानना चाहता हूं कि वास्तव में मैं क्या करना चाहता हूं।

मुझे आशा है कि मैंने आपको मौत के लिए जन्म नहीं दिया! आपकी अंतर्दृष्टि के लिए अग्रिम धन्यवाद।

+1

आप पिक्सेल द्वारा पिक्सेल चित्रित कर रहे हैं ?? (zomg !!) – UmNyobe

उत्तर

4

गैर ओपन समाधान:

गंतव्य छवि के लिए एक आरजीबी बफर का प्रयोग करें। जैसा आपने पहले किया था अपने 3 पहले चरणों के माध्यम से कार्य करें। एक बार आपको स्थिति और पिक्सेल रंग मिल गया है, तो आप इसे इस बफर पर सेट करते हैं। फिर आप पिछले बफर के आधार पर छवि बनाने के लिए

QImage::QImage (uchar * data, int width, int height, Format format) 

का उपयोग करें। यह आपके द्वारा प्रदत्त समाधान के करीब है और आपके पास वर्तमान में जो कुछ है उससे कहीं अधिक तेज़ होगा।

+0

बहुत धन्यवाद!मैं शायद इसका उपयोग करूंगा (जब तक मैं किसी दिन ओपनजीएल के बारे में नहीं सीखता)। – Seub

+2

मैं पुष्टि करता हूं, यह मेरे लिए ठीक है! (अधिकतम 0.04s में paintEvent) – Seub

7

ओपनजीएल छवि (बनावट) समन्वय मैपिंग वास्तव में अच्छी तरह से करता है। आप शायद ओपनजीएल के कुछ रूपों का उपयोग करना चाहते हैं। क्यूटी के पास ओपनजीएल के लिए कुछ बाध्यकारी है जो आपकी मदद कर सकता है।

+0

+1 सहमत है, ओपी एक यूवी मैपिंग ऐप बना रहा है, ओपनजीएल इसके लिए एकदम सही टूल है। – cmannett85

+0

आपके उत्तर के लिए धन्यवाद! मैं निश्चित रूप से इस दिन में देख लूंगा। समस्या यह है कि मैं ओपनजीएल के बारे में कुछ भी नहीं जानता। – Seub

3

ऐसा करने का एक तरीका QGraphicsScene/QGraphicsView कॉम्बो के बजाय QGLWidget से विरासत में प्राप्त कक्षा का उपयोग करना होगा। दुर्भाग्य से, ओपनजीएल के लिए सीखने की वक्र थोड़ा खड़ी शुरू होती है। हालांकि, यह बहुत तेज़ होगा क्योंकि यह सीधे ग्राफिक्स कार्ड पर होगा जो इस तरह के ऑपरेशन के लिए अनुकूलित है।
आप छवि QGLWidget::bindTexture() लोड करेंगे।
आप छवि में अपने त्रिकोण जाल के साथ अंक जोड़ देंगे और उन्हें अपने ग्राफिक्स कार्ड पर भेजेंगे।

glEnable(GL_TEXTURE_2D); 

glBegin(GL_TRIANGLES); 
for (int ii=0;ii<triangle.size();++ii) { 
    for (int jj=0;jj<3;++jj) { 
    glTexCoord2d(triangle[ii].tex[jj][0],triangle[ii].tex[jj][1]); 
    glVertex2d(triangle[ii].point[jj[0],triangle[ii].point[jj][1]); 
    } 
} 
glEnd(); 

triangle कहाँ कुछ डेटा संरचना है कि आप त्रिकोण कोने पकड़े लगा रहे: ओपन (जो मेरी राय में नए एपीआई से उपयोग करने के लिए आसान है) की विरासत संस्करण में, यह कुछ इस तरह दिखेगा और छवि में जुड़े मैपिंग्स। ग्राफिक्स कार्ड आपके लिए पिक्सेल इंटरपोलेशन को संभालेगा।

+0

आपके उत्तर के लिए बहुत बहुत धन्यवाद! यह बहुत दिलचस्प है। "दुर्भाग्य से, ओपनजीएल के लिए सीखने की वक्र थोड़ा खड़ी शुरू होती है"। मुझे लगता है कि यह मेरे लिए समस्या है! लेकिन मुझे शायद किसी बिंदु पर इसके बारे में जानना होगा। – Seub

+0

यह बहिष्कृत कोड का उपयोग करता है। आप वास्तव में शेडर्स और बनावट नमूने का उपयोग करना चाहते हैं। – doron

+0

@ डोरन इसे हटा दिया गया है। लेकिन अगर फिक्स्ड-पाइपलाइन कार्यक्षमता नौकरी करेगी, तो इस तरह से जाना बहुत आसान है। जीएलएसएल केवल 3 डी प्रोग्रामिंग सीखने में कठिनाई को बढ़ाता है। यह अधिक लचीलापन देता है, लेकिन असेंबली कोड भी करता है। फिर भी, एक कारण है कि हम में से अधिकांश असेंबली में ज्यादा कार्यक्रम नहीं करते हैं। – JCooper

1

ओपनजीएल के अलावा एक अन्य विकल्प ओपनसीएल का उपयोग करना है, जो आपके लिए आसान हो सकता है। आपको बस ग्राफिक्स कार्ड में इनपुट/आउटपुट बिटमैप को मैप करना होगा, सी में एक छोटा कर्नेल लिखें जो एक त्रिकोण को संभालता है, और फिर प्रत्येक त्रिकोण के लिए कर्नेल निष्पादन कतारबद्ध करता है। यह सीपीयू पर एक कोर के रूप में जितना तेज़ 100x काम करेगा।

OpenCL मेजबान एपीआई यहाँ के लिए एक क्यूटी आवरण नहीं है:

http://doc.qt.digia.com/opencl-snapshot/index.html

0

एक अलग दृष्टिकोण कतरन और परिवर्तनों को पहले से ही रेखापुंज रंग इंजन के भीतर कुशलतापूर्वक कार्यान्वित लाभ उठाने के लिए है। जब तक दो त्रिकोणों के बीच परिवर्तन 3x3 संवर्धित परिवर्तन मैट्रिक्स का उपयोग करके व्यक्त किया जा सकता है, तो आपको केवल इसे लक्षित चित्रकार पर सेट करने की आवश्यकता होती है, और फिर संपूर्ण स्रोत छवि को लक्ष्य पर खींचें। यह लक्ष्य त्रिकोण को भरने के लिए फिसल जाएगा और बदल जाएगा। अगर प्रोफाइलिंग इसका लाभ दिखाती है, तो आप पूरी छवि के बजाए स्रोत त्रिकोण के बाउंडिंग रेक्ट को भी खींच सकते हैं।

इसे समांतर किया जा सकता है ताकि आप सीपीयू कोर के समानांतर में कई त्रिकोणों को संसाधित कर सकें।

संबंधित मुद्दे