2012-08-12 9 views
30

Responding to Touch Events एंड्रॉइड ट्यूटोरियल के संबंध में किसी अन्य उपयोगकर्ता की मदद करने के बाद, मैंने सोर्स कोड डाउनलोड किया, और मैंने जो देखा उससे काफी परेशान था। ट्यूटोरियल यह तय करने में सक्षम नहीं है कि वह पंक्ति वैक्टर या कॉलम वैक्टर का उपयोग करना चाहता है, और यह सब मुझे मिश्रित दिखता है।क्या Google का एंड्रॉइड ओपनजीएल ट्यूटोरियल गलत रैखिक बीजगणित पढ़ रहा है?

एंड्रॉयड मैट्रिक्स पृष्ठ पर, वे दावा है कि उनके सम्मेलन स्तंभ वेक्टर/स्तंभ-प्रमुख, जो ओपन की खासियत है है।

क्या मैं सही हूं, या क्या मुझे कुछ याद आ रही है? यहां इसकी प्रासंगिक बिट्स हैं:

mProjMatrix * mVMatrix को गुणा करके एमवीपीमैट्रिक्स बनाकर प्रारंभ करें। अब तक सब ठीक है।

// Set the camera position (View matrix) 
    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 

    // Calculate the projection and view transformation 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0) 

अगला वे MVPMatrix के बाएं हाथ की ओर करने के लिए एक रोटेशन जोड़कर कर रहे हैं? यह थोड़ा अजीब लगता है। गैर स्थानांतरित क्रम में

// Create a rotation for the triangle 
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f); 

    // Combine the rotation matrix with the projection and camera view 
    Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0) 

अपलोड कर रहा है।

GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); 

अंत में उनके शेडर में

, एक वेक्टर * आव्यूह गुणन?

// the matrix must be included as a modifier of gl_Position 
    " gl_Position = vPosition * uMVPMatrix;" 

यह सब एक साथ जोड़ा जा रहा है, हम पाते हैं:

gl_Position = vPosition * mRotation * mProjection * mView; 

कौन सा मेरी कल्पना के किसी भी खिंचाव से सही नहीं है। क्या कोई स्पष्टीकरण है कि मैं यह नहीं देख रहा हूं कि यहां क्या हो रहा है?

+2

मेरे लिए दो संभावनाएं। या तो उदाहरण गलत है या उन्होंने मैट्रिक्स संचालन को अलग-अलग लागू किया है। [देखें] (http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/opengl/Matrix.java) –

+0

क्या आप स्पष्टीकरण दे सकते हैं समस्या, कृपया? – user1071136

उत्तर

25

उस व्यक्ति के रूप में जिसने ओपनजीएल ट्यूटोरियल लिखा था, मैं पुष्टि कर सकता हूं कि उदाहरण कोड गलत है। विशेष रूप से, शेडर कोड में कारकों में से आदेश वापस ले लिया जाना चाहिए:

" gl_Position = uMVPMatrix * vPosition;" 

रोटेशन मैट्रिक्स के आवेदन करने के लिए के रूप में, कारकों में से आदेश भी उलट किया जाना चाहिए ताकि रोटेशन पिछले कारक है। अंगूठे का नियम यह है कि मैट्रिस दाएं से बाएं क्रम में लागू होते हैं, और घूर्णन पहले लागू होता है (यह "एमवीपी" का "एम" हिस्सा है), इसलिए इसे सबसे सही ऑपरेंड होना चाहिए। इसके अलावा, आप इस गणना के लिए एक खरोंच मैट्रिक्स का उपयोग करना चाहिए, के रूप में (अपने अधिक पूरा जवाब, नीचे देखें) इयान नी-लुईस द्वारा सिफारिश की: इस समस्या की ओर ध्यान फोन करने के लिए

float[] scratch = new float[16]; 
// Combine the rotation matrix with the projection and camera view 
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); 

धन्यवाद। मुझे जितनी जल्दी हो सके प्रशिक्षण कक्षा और नमूना कोड तय किया जाएगा।

संपादित करें: इस समस्या को अब डाउनलोड करने योग्य नमूना कोड और ओपनजीएल ईएस प्रशिक्षण कक्षा में सही किया गया है, जिसमें कारकों के सही क्रम पर टिप्पणियां शामिल हैं। फीडबैक के लिए धन्यवाद, दोस्तों!

+2

एक अतिरिक्त मुद्दा है: Matrix.multiplyMM एलियासिंग की जांच नहीं करता है। यदि आप आउटपुट पैरामीटर के रूप में इनपुट पैरामीटर में से एक का पुन: उपयोग करते हैं, तो इसे ओवरराइट कर दिया जाएगा। –

+0

धन्यवाद मैं इस उत्तर की तलाश में था। और 'वर्दी mat4 uMVPMatrix' को 'शून्य मुख्य' से पहले जोड़ा जाना चाहिए या यह clearColor के साथ एक खाली स्क्रीन देगी। –

+0

इसके अलावा मुझे 'Matrix.multiplyMM (mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0) मिला; 'पुनः आदेशित एक से सही रोटेशन रूपांतरण देने के लिए। 'टी (एक्स) = एएक्स' और 'मल्टीप्लाईएमएम (फ्लोट [] परिणाम, int परिणाम ऑफसेट, फ्लोट [] एलएचएस, int lhs ऑफसेट, फ्लोट [] rhs, int rhsOffset)'। केवल वेरटेक्स शेडर को ठीक करने के लिए मेरे लिए काम किया। –

10

ट्यूटोरियल गलत है, लेकिन गलतियों से कई या तो एक दूसरे को रद्द या नहीं (फिक्स्ड कैमरा 0,0 पर (केंद्रित), रोटेशन के आसपास जेड केवल) इस बहुत ही सीमित संदर्भ में स्पष्ट कर रहे हैं। घूर्णन पीछे की तरफ है, लेकिन अन्यथा यह सही दिखता है।(यह देखने के लिए कि यह गलत क्यों है, कम मामूली कैमरा आज़माएं: आंखें सेट करें और उदाहरण के लिए y = 1 पर देखें।)

ऐसी चीजों में से एक जो डीबग करने के लिए बहुत कठिन बना देता है यह है कि मैट्रिक्स विधियां नहीं हैं अपने इनपुट पर कोई उपनाम पहचान करें। ट्यूटोरियल कोड ऐसा लगता है जैसे आप Matrix.multiplyMM को एक ही मैट्रिक्स के साथ इनपुट और परिणाम दोनों के रूप में उपयोग कर सकते हैं। यह सच नहीं है। लेकिन चूंकि कार्यान्वयन एक समय में एक स्तंभ को गुणा करता है, यह बहुत कम स्पष्ट है कि दाएं हाथ की ओर पुन: उपयोग किए जाने पर दाएं हाथ की ओर पुन: उपयोग किए जाने पर कुछ गलत है (वर्तमान कोड में, जहां एमएमवीपीमैट्रिक्स rhs और परिणाम है) । बाईं ओर प्रत्येक कॉलम को परिणाम में संबंधित कॉलम से पहले पढ़ा जाता है, इसलिए एलएचएस ओवरराइट होने पर भी आउटपुट सही होगा। लेकिन अगर दाएं हाथ की तरफ परिणाम के समान होता है, तो इसका पहला कॉलम पढ़ा जाने से पहले ओवरराइट हो जाएगा।

तो ट्यूटोरियल कोड स्थानीय अधिकतम प्रकार पर है: ऐसा लगता है जैसे यह काम करता है, और यदि आप किसी एक चीज को बदलते हैं, तो यह शानदार रूप से टूट जाता है। जो किसी को यह मानने के लिए प्रेरित करता है कि यह गलत लगता है, यह सही हो सकता है। ;-)

वैसे भी, यहां कुछ प्रतिस्थापन कोड है जो मुझे लगता है कि इच्छित परिणाम है।

जावा कोड:

@Override 
public void onDrawFrame(GL10 unused) { 
    float[] scratch = new float[16]; 

    // Draw background color 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

    // Set the camera position (View matrix) 
    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 

    // Calculate the projection and view transformation 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0); 

    // Draw square 
    mSquare.draw(mMVPMatrix); 

    // Create a rotation for the triangle 
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, 1.0f); 

    // Combine the rotation matrix with the projection and camera view 
    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); 

    // Draw triangle 
    mTriangle.draw(scratch); 
} 

छायांकर्ता कोड:

gl_Position = uMVPMatrix * vPosition; 

एनबी: इन सुधारों प्रक्षेपण सही हैं, लेकिन वे भी रोटेशन की दिशा रिवर्स। ऐसा इसलिए है क्योंकि मूल कोड ने गलत क्रम में परिवर्तनों को लागू किया था। इस बारे में सोचें: ऑब्जेक्ट को घड़ी की दिशा में घूर्णन करने के बजाय, यह कैमरे को घुमावदार घुमा रहा था। जब आप संचालन के क्रम को ठीक करते हैं ताकि रोटेशन कैमरे के बजाए ऑब्जेक्ट पर लागू हो, तो ऑब्जेक्ट काउंटरक्लॉक वार पर जा रहा है। यह मैट्रिक्स नहीं है जो गलत है; यह कोण है जो मैट्रिक्स बनाने के लिए उपयोग किया गया था।

तो 'सही' परिणाम प्राप्त करने के लिए, आपको भी मैंगल के संकेत को फ़्लिप करने की आवश्यकता है।

1

मैं एक ही मुद्दे पर काम कर रहा हूँ और है कि मैं क्या मिला है:

मेरा मानना ​​है कि जो नमूना सही है,
सहित शेडर कोड में कारकों में से आदेश:

gl_Position = vPosition * uMVPMatrix; 

इसे सत्यापित करने के लिए त्रिकोण को उलटा कारकों के क्रम के साथ घुमाएं, यह त्रिभुज को 90 डिग्री पर गायब करने के लिए फैलाएगा।

असली समस्या setLookAtM फ़ंक्शन में प्रतीत होती है।
जो नमूना पैरामीटर में कर रहे हैं:

Matrix.setLookAtM(mVMatrix, 0, 
    0f, 0f,-3f, 0f, 0f, 0f, 0f, 1f, 0f); 

जो साथ ही पूरी तरह से तार्किक है।
हालांकि, जिसके परिणामस्वरूप दृश्य मैट्रिक्स मुझे अजीब लग रहा है:

-1 0 0 0 
0 1 0 0 
0 0 -1 0 
0 0 -3 1 

हम देख सकते हैं, इस मैट्रिक्स को उलटने के एक्स समन्वय, के बाद से पहली सदस्य -1 है जाएगा,
जो बायीं/दायीं को बढ़ावा मिलेगा स्क्रीन पर फ्लिप करें।
यह जेड-ऑर्डर को भी उलट देगा, लेकिन चलिए एक्स समन्वय पर ध्यान केंद्रित करते हैं।

मुझे लगता है कि setLookAtM फ़ंक्शन भी सही तरीके से काम कर रहा है।
हालांकि, चूंकि मैट्रिक्स क्लास ओपनजीएल का हिस्सा नहीं है, यह कुछ अन्य निर्देशांक सिस्टम,
उदाहरण के लिए उपयोग कर सकता है - वाई अक्ष के साथ नियमित स्क्रीन समन्वय नीचे इंगित करता है।
यह सिर्फ एक अनुमान है, मैंने वास्तव में इसे सत्यापित नहीं किया था।

संभावित समाधान:
हम वांछनीय दृश्य मैट्रिक्स निर्माण कर सकते हैं मैन्युअल रूप से,
कोड है:

Matrix.setIdentityM(mVMatrix,0); 
mVMatrix[14] = -3f; 

या
हम इसे देने उलट कैमरा निर्देशांक द्वारा setLookAtM चाल करने के लिए समारोह की कोशिश कर सकते हैं: 0, 0, +3 (-3 के बजाय)।

Matrix.setLookAtM(mVMatrix, 0, 
    0f, 0f, 3f, 0f, 0f, 0f, 0f, 1f, 0f); 

जिसके परिणामस्वरूप दृश्य मैट्रिक्स होगा:

1 0 0 0 
0 1 0 0 
0 0 1 0 
0 0 -3 1 

है यही है कि हम क्या जरूरत है।
अब कैमरा अपेक्षित व्यवहार करता है,
और नमूना सही ढंग से काम करता है।

+1

आप सही हैं कि शेडर में ऑपरेंड के आदेश को ठीक करने से बेहतर होगा, न कि बेहतर, परिणाम। लेकिन ऐसा इसलिए है क्योंकि नमूना के साथ एक से अधिक समस्याएं हैं। –

+0

मुझे यह उल्लेख करना चाहिए कि आपका समाधान वास्तव में पहली चीज थी जिसकी मैंने कोशिश की थी, क्योंकि मुझे विश्वास था कि मैं एक सौहार्द समस्या देख रहा था। लेकिन भले ही यह सही दिखता है, यह नहीं है; कैमरे को थोड़ा घुमाने और घूमने का प्रयास करें और आप तुरंत देखेंगे क्यों। नीचे पोस्ट किया गया कोड सही है। –

2

मैं इस प्रकार इस समस्या का समाधान:

@Override 
public void onDrawFrame(GL10 unused) {  
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);   

    Matrix.setRotateM(mModelMatrix, 0, mAngle, 0, 0, 1.0f); 
    Matrix.translateM(mModelMatrix, 0, 0.4f, 0.0f, 0); 

    mSquare.draw(mProjMatrix,mViewMatrix,mModelMatrix); 
} 

@Override 
public void onSurfaceChanged(GL10 unused, int width, int height) { 
    ... 
    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 99); 

} 

class Square { 

    private final String vertexShaderCode = 
     "uniform mat4 uPMatrix; \n" + 
     "uniform mat4 uVMatrix; \n" + 
     "uniform mat4 uMMatrix; \n" + 

     "attribute vec4 vPosition; \n" + 
     "void main() { \n" + 
     " gl_Position = uPMatrix * uVMatrix * uMMatrix * vPosition; \n" + 
     "} \n"; 

    ... 

    public void draw(float[] mpMatrix,float[] mvMatrix,float[]mmMatrix) { 

     ... 

     mPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uPMatrix"); 
     mVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uVMatrix"); 
     mMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix"); 

     GLES20.glUniformMatrix4fv(mPMatrixHandle, 1, false, mpMatrix, 0); 
     GLES20.glUniformMatrix4fv(mVMatrixHandle, 1, false, mvMatrix, 0); 
     GLES20.glUniformMatrix4fv(mMMatrixHandle, 1, false, mmMatrix, 0); 

     ... 
    } 
} 
0

कोई अन्य सुझाव मेरे लिए काम किया के अलावा वर्तमान अपडेट किए गए Android उदाहरण कोड का उपयोग करते समय निम्न त्रिकोण स्थानांतरित करने के लिए कोशिश कर रहा।

निम्नलिखित लिंक में उत्तर शामिल है। इसे खोजने के लिए एक दिन से अधिक समय लगा। दूसरों को मदद करने के लिए यहां पोस्ट करना क्योंकि मैंने इस पोस्ट को कई बार देखा था। OpenGL ES Android Matrix Transformations

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