2010-02-13 14 views
23

मुझे कुछ 2 डी ज्यामिति मिली है। मैं अपनी ज्यामिति के चारों ओर कुछ बाध्यकारी रेक्ट लेना चाहता हूं, और उसके बाद विमान पर कहीं और इसका एक छोटा संस्करण प्रस्तुत करना चाहता हूं। यहाँ और अधिक या कम कोड मैं स्केलिंग और अनुवाद क्या करना है:ओपनजीएल: स्केल फिर अनुवाद करें? और कैसे?

// source and dest are arbitrary rectangles. 
float scaleX = dest.width/source.width; 
float scaleY = dest.height/source.height; 
float translateX = dest.x - source.x; 
float translateY = dest.y - source.y; 

glScalef(scaleX, scaleY, 0.0); 
glTranslatef(translateX, translateY, 0.0); 
// Draw geometry in question with its normal verts. 

यह काम करता है ठीक किसी दिए गए आयाम के लिए अपेक्षा के गंतव्य मूल 0. है लेकिन के लिए, कहते हैं, एक्स मूल है, अशून्य है, परिणाम अभी भी सही ढंग से स्केल किया गया है लेकिन ऐसा लगता है कि (?) किसी अक्ष पर शून्य के करीब किसी चीज़ का अनुवाद किया गया है - यह पता चला है कि यह बिल्कुल वैसा ही नहीं है जैसे dest.x शून्य था।

कोई व्यक्ति कुछ स्पष्ट बता सकता है कि मुझे याद आ रही है?

धन्यवाद!

अंतिम अपडेट बहबर और मार्कस के उत्तर प्रति नीचे, मैंने कुछ और प्रयोग किया और इसे हल किया। एडम बोवेन की टिप्पणी टिप बंद थी। मुझे दो महत्वपूर्ण तथ्य याद आ रहे थे:

  1. मुझे जिस ज्यामिति की परवाह है, उसके केंद्र में स्केलिंग करने की आवश्यकता है।
  2. मुझे अंतर्ज्ञान के विपरीत क्रम में परिवर्तनों को लागू करने की आवश्यकता है (मेरे लिए)।

पहले पीछे की ओर स्पष्ट है। लेकिन उत्तरार्द्ध के लिए, मेरे जैसे अन्य अच्छे प्रोग्रामर/खराब गणितज्ञों के लिए: मेरा अंतर्ज्ञान बदल रहा है Red Book में "ग्रैंड, फिक्स्ड कोऑर्डिनेट सिस्टम" कहलाता है, जिसमें एक पूर्ण विमान है, और आपकी ज्यामिति उस पर घूमती है ट्रांसफॉर्म का उपयोग कर विमान। यह ठीक है, लेकिन एक मैट्रिक्स में एकाधिक परिवर्तनों को ढेर करने के पीछे गणित की प्रकृति को देखते हुए, यह विपरीत है कि चीजें वास्तव में कैसे काम करती हैं (नीचे दिए गए उत्तरों या अधिक के लिए लाल पुस्तक देखें)। असल में, ट्रांसफॉर्म "रिवर्स ऑर्डर" में "लागू" होते हैं ताकि वे कोड में कैसे दिखाई दे सकें। यहाँ अंतिम काम कर समाधान है:

// source and dest are arbitrary rectangles. 
float scaleX = dest.width/source.width; 
float scaleY = dest.height/source.height; 
Point sourceCenter = centerPointOfRect(source); 
Point destCenter = centerPointOfRect(dest); 

glTranslatef(destCenter.x, destCenter.y, 0.0); 
glScalef(scaleX, scaleY, 0.0); 
glTranslatef(sourceCenter.x * -1.0, sourceCenter.y * -1.0, 0.0); 
// Draw geometry in question with its normal verts. 

उत्तर

16

ओपनजीएल में, आपके द्वारा निर्दिष्ट मैट्रिक्स मौजूदा मैट्रिक्स के दाईं ओर गुणा किए जाते हैं, और वर्टेक्स अभिव्यक्ति के बहुत दूर है।

इस प्रकार, आपके द्वारा निर्दिष्ट अंतिम ऑपरेशन ज्यामिति की समन्वय प्रणाली में ही है। (पहला आम तौर पर व्यू ट्रांसफॉर्म होता है, यानी आपके कैमरे के टू-वर्ल्ड ट्रांसफॉर्म के विपरीत।)

बहबर एक अच्छा मुद्दा बनाता है कि आपको स्केलिंग के लिए केंद्र बिंदु पर विचार करने की आवश्यकता है। (या घूर्णन के लिए पिवट बिंदु।) आमतौर पर आप वहां अनुवाद करते हैं, घूमते/स्केल करते हैं, फिर वापस अनुवाद करते हैं। (या सामान्य रूप से, आधार परिवर्तन, ऑपरेशन, फिर उलटा लागू)।इसे Change of Basis कहा जाता है, जिसे आप पढ़ना चाहेंगे।

वैसे भी, (शायद एक एनीमेशन) यह कैसे काम करता, (, आदि शून्य) कुछ सरल मूल्यों के साथ की कोशिश तो उन्हें थोड़ा बदल के बारे में कुछ अंतर्ज्ञान पाने और देखते हैं कि उत्पादन के साथ होता है। फिर यह देखना बहुत आसान है कि आपके परिवर्तन वास्तव में आपकी ज्यामिति में क्या कर रहे हैं।

अद्यतन

आदेश है "उलट" यह w.r.t. शुरुआती ओपनजीएल-कोडर्स के बीच अंतर्ज्ञान सामान्य है। मैं कंप्यूटर ग्राफिक्स कोर्स पढ़ रहा हूं और कई इसी तरह प्रतिक्रिया करते हैं। अगर आप ट्रांसफॉर्म और ज्यामिति के पेड़ (दृश्य-ग्राफ) को प्रस्तुत करते समय पुशमैट्रिक्स/पॉपमैट्रिक्स के उपयोग पर विचार करते हैं तो ओपनजीएल कैसे करता है, इस बारे में सोचना आसान हो जाता है। फिर वर्तमान क्रम-चीजें बल्कि प्राकृतिक हो जाती हैं, और इसके विपरीत कुछ भी उपयोगी होने में मुश्किल होती है।

+1

संक्षेप में, ऑर्डर को glTranslate (dest) में बदलें; glScale (पैमाने); glTranslate (स्रोत); –

+0

एडम: जैसा कि आप सुझाव देते हैं, यह काम नहीं करता है, हालांकि मैं चिंतित हूं - क्या आप इस बारे में विस्तार से बता सकते हैं कि ऑर्डरिंग क्यों होगी, और संभवतः यह एक स्पष्ट विचार प्रदान करेगा कि यह मौजूदा कोड के सापेक्ष कैसा दिखता है ? शायद मैं सिर्फ अपने छद्म कोड का गलत व्याख्या कर रहा हूं। धन्यवाद! –

+0

कभी नहीं: इस मामले में "काम नहीं करता" एक fatfingered मूल्य था। इसे ठीक करने के बाद, हम व्यवसाय में हैं। अधिक के लिए अद्यतन प्रश्न देखें। धन्यवाद! –

6

स्केल, बस घुमाएँ की तरह, मूल से चल रही है। इसलिए यदि आप सेगमेंट तक फैले आधा ऑब्जेक्ट स्केल करते हैं [10:20] (धुरी एक्स पर, उदाहरण के लिए), तो आपको [5:10] मिलता है। इसलिए ऑब्जेक्ट स्केल किया गया था, और मूल के करीब चले गए। वास्तव में आपने क्या देखा।

यही कारण है कि आप सामान्य रूप से स्केल को पहले लागू करते हैं (क्योंकि वस्तुओं को 0 के आसपास परिभाषित किया जाता है)।

तो यदि आप बिंदु केंद्र के चारों ओर एक वस्तु को स्केल करना चाहते हैं, तो आप ऑब्जेक्ट को केंद्र से मूल तक, वहां स्केल कर सकते हैं और वापस अनुवाद कर सकते हैं।

साइड नोट, यदि आप पहले अनुवाद करते हैं, और फिर स्केल करते हैं, तो आपका स्केल पिछले अनुवाद पर लागू होता है, यही कारण है कि आपको शायद इस विधि के साथ समस्याएं थीं।

+0

उत्तर के लिए धन्यवाद। क्या आप एक मैट्रिक्स-गणित के लिए वर्तनी कर सकते हैं कि उचित अनुवाद-से-मूल, फिर स्केल, फिर अनुवाद-बैक करने के लिए मैं क्या करूँगा? मैंने ज्यामिति को चित्रित करने से पहले तीनों कॉलों में उत्तराधिकार में इन तीन चीजों को ढंकने का प्रयास किया (स्रोत उत्पत्ति के नकारात्मक द्वारा अनुवादित किया गया, फिर स्केल कारकों द्वारा स्केल करें, फिर नियत उत्पत्ति द्वारा अनुवाद करें) लेकिन कोई दृश्य परिणाम नहीं मिला। –

+0

आह, शायद मुझे उत्पत्ति के बजाय रेक्ट के केंद्र के सापेक्ष अनुवाद करना होगा। की कोशिश करेंगे। –

+0

नहीं। इसके साथ कोई पासा नहीं: अनुवाद-दर-नकारात्मक-स्रोत-स्रोत, फिर स्केल, फिर अनुवाद-द्वारा-पॉजिटिव-सेंटर-ऑफ-डिस्ट। –

1

मैं OpenGL ES, ओपन के साथ सिर्फ एक बिट के साथ नहीं खेला है।

ऐसा लगता है कि आप मूल के विपरीत एक अलग स्थिति से बदलना चाहते हैं, निश्चित नहीं है, लेकिन क्या आप ट्रांसफॉर्म करने की कोशिश कर सकते हैं और glPushMatrix() and glPopMatrix() के भीतर उस बिट को खींच सकते हैं?

e.g. 

// source and dest are arbitrary rectangles. 
float scaleX = dest.width/source.width; 
float scaleY = dest.height/source.height; 
float translateX = dest.x - source.x; 
float translateY = dest.y - source.y; 

glPushMatrix(); 
    glScalef(scaleX, scaleY, 0.0); 
    glTranslatef(translateX, translateY, 0.0); 
    // Draw geometry in question with its normal verts. 
    //as if it were drawn from 0,0 
glPopMatrix(); 

यहाँ एक सरल प्रसंस्करण स्केच मैं बिंदु को वर्णन लिखा है:

import processing.opengl.*; 
import javax.media.opengl.*; 


void setup() { 
    size(500, 400, OPENGL); 
} 

void draw() { 
    background(255); 
    PGraphicsOpenGL pgl = (PGraphicsOpenGL) g; 
    GL gl = pgl.beginGL(); 


    gl.glPushMatrix(); 
    //transform the 'pivot' 
    gl.glTranslatef(100,100,0); 
    gl.glScalef(10,10,10); 
    //draw something from the 'pivot' 
    gl.glColor3f(0, 0.77, 0); 
    drawTriangle(gl); 
    gl.glPopMatrix(); 
    //matrix poped, we're back to orginin(0,0,0), continue as normal 
    gl.glColor3f(0.77, 0, 0); 
    drawTriangle(gl); 
    pgl.endGL(); 
} 

void drawTriangle(GL gl){ 
    gl.glBegin(GL.GL_TRIANGLES); 
    gl.glVertex2i(10, 0); 
    gl.glVertex2i(0, 20); 
    gl.glVertex2i(20, 20); 
    gl.glEnd(); 
} 

यहाँ स्केच चल की एक छवि है, एक ही हरी त्रिकोण अनुवाद और पैमाने के साथ तैयार की है, लागू किया है, तो लाल एक, धक्का/पॉप 'ब्लॉक', तो यह बदलने से प्रभावित नहीं है outsie:

alt text

HTH, जीई ऑर्गे

+0

धन्यवाद जॉर्ज, लेकिन पुश/पॉप वास्तव में मुद्दा नहीं है; मैं कोड के बाहर पहले से ही पुश/पॉप कर रहा हूं जिसे मैंने स्निपेट बनाया है। चित्रों के साथ चित्रण के लिए धन्यवाद, यद्यपि! एक अच्छा दृश्यता। –

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