2012-11-20 16 views
8

मेरे पास एक प्रस्तुतकर्ता है जो GLSurfaceView.Renderer इंटरफेस को कार्यान्वित करता है; GLSurfaceView का एक सबक्लास और मेरी ऑब्जेक्ट्स का प्रतिनिधित्व करने वाली कुछ कक्षाएं मैं आकर्षित करना चाहता हूं। मेरे पास http://developer.android.com/training/graphics/opengl/motion.html से कोड है, मैं इसे विस्तारित करना चाहता हूं और कुछ अक्षों के साथ आगे बढ़ना चाहता हूं और इसे प्रबंधित नहीं कर सकता। वस्तु केवल घूर्णन है। और यहाँ मेरे कोड है:ओपनजीएल ईएस एंड्रॉइड मैट्रिक्स ट्रांसफॉर्मेशन

public class NotMyCoolRenderer implements GLSurfaceView.Renderer { 

public GLShip mTriangle; 
private GLBackgroundStar mSquare; 

private final float[] mMVPMatrix = new float[16]; 
private final float[] mProjMatrix = new float[16]; 
private final float[] mVMatrix = new float[16]; 
private final float[] mModelMatrix = new float[16]; 
private final float[] tempMatrix = new float[16]; 

public void onDrawFrame(GL10 unused) { 
    // 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); 
    // Now moving on to triangle aka ship 
    Matrix.setIdentityM(mModelMatrix, 0); 
    Matrix.translateM(mModelMatrix, 0, 0.1f, 0f, 0); 
    Matrix.rotateM(mModelMatrix, 0, mTriangle.mAngle, 0, 0, -1.0f); 
    Matrix.multiplyMM(tempMatrix, 0, mVMatrix, 0, mProjMatrix, 0); 
    Matrix.multiplyMM(mMVPMatrix, 0, mModelMatrix , 0, tempMatrix , 0); 

    // Draw triangle 
    mTriangle.draw(mMVPMatrix); 
} 
public void onSurfaceChanged(GL10 unused, int width, int height) { 
    // Adjust the viewport based on geometry changes, 
    // such as screen rotation 
    GLES20.glViewport(0, 0, width, height); 

    float ratio = (float) width/height; 

    // this projection matrix is applied to object coordinates 
    // in the onDrawFrame() method 
    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 

} 

public class GLShip { 
    public volatile float mAngle; 
    private final String vertexShaderCode = 
     // This matrix member variable provides a hook to manipulate 
     // the coordinates of the objects that use this vertex shader 
     "uniform mat4 uMVPMatrix;" + 

     "attribute vec4 vPosition;" + 
     "void main() {" + 
     // the matrix must be included as a modifier of gl_Position 
     " gl_Position = uMVPMatrix * vPosition;" + 
     "}"; 


    public void draw(float[] mvpMatrix) { 
     // Add program to OpenGL environment 
     GLES20.glUseProgram(mProgram); 

     // get handle to vertex shader's vPosition member 
     mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); 

     // Enable a handle to the triangle vertices 
     GLES20.glEnableVertexAttribArray(mPositionHandle); 

     // Prepare the triangle coordinate data 
     GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, 
            GLES20.GL_FLOAT, false, 
            vertexStride, vertexBuffer); 

     // get handle to fragment shader's vColor member 
     mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); 

     // Set color for drawing the triangle 
     GLES20.glUniform4fv(mColorHandle, 1, color, 0); 

     // get handle to shape's transformation matrix 
     mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 
     NotMyCoolRenderer.checkGlError("glGetUniformLocation"); 

     // Apply the projection and view transformation 
     GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); 
     NotMyCoolRenderer.checkGlError("glUniformMatrix4fv"); 

     // Draw the triangle 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); 

     // Disable vertex array 
     GLES20.glDisableVertexAttribArray(mPositionHandle); 
    } 
} 

मेरे उम्मीदों कि प्रत्येक वस्तु redrawing पर वध तक घुमाया और 1f द्वारा y- अक्ष traslated से भरे जाएंगे। मैं केवल घूर्णन (थोड़ा अनुमानित) देख सकता हूं हालांकि। मुझे वास्तव में इसके बारे में कुछ प्रश्न हैं: मैं अपना अनुवाद मैट्रिक्स कैसे लागू करूं और ओपनजी कार्यक्षमता को विभाजित करने का सबसे अच्छा अभ्यास क्या है? मॉडल मैट्रिक्स को प्रस्तुतकर्ता के बजाए ऑब्जेक्ट में ही संग्रहीत नहीं किया जाना चाहिए? क्या मैट्रिक्स ऑपरेशंस को रेंडरर-क्लास में किया जाना चाहिए? मैंने उन्हें एक साथ समूहीकृत किया है क्योंकि मुझे लगता है कि वे सभी संबंधित हैं।

+0

हम्म। अभी भी यह समझाने के लिए कुछ भी नहीं है कि mProjMatrix कैसे प्रारंभ किया गया है। –

+0

यहां एक अंतिम संकेत दिया गया है: http://learningwebgl.com/blog/?page_id=1217 से पाठों को चरणबद्ध करके चरण दोहराने का प्रयास करें। इसमें केवल जावास्क्रिप्ट शामिल है, लेकिन अंतर न्यूनतम के बगल में हैं। एपीआई वही है और मैट्रिक्स गणित वही है। सौभाग्य! –

+0

@AkiSuihkonen एक और [थ्रेड] में (http://stackoverflow.com/questions/11925647/is-googles-android-opengl-tutorial-teaching-incorrect-linear-algebra) लोगों ने सुझाव दिया (उसी ट्यूटोरियल के उसी कोड के लिए) 'gl_Position = uMVPMatrix * vPosition;' का उपयोग करके 'gl_Position = vPosition * uMVPMatrix; '। अगर मैं सुझाव का पालन करता हूं, तो मैं अपने त्रिकोण को सभी –

उत्तर

17

मैंने एंड्रॉयड प्रशिक्षण से उदाहरण के साथ काम कर, निम्नलिखित दृष्टिकोण अंत में मेरे लिए काम करता है। (Android Training > Displaying Graphics with OpenGL ES > Adding Motion के आधार पर)

  1. सही शीर्ष शेडर का उपयोग करें:

    private final String vertexShaderCode = 
    // This matrix member variable provides a hook to manipulate 
    // the coordinates of the objects that use this vertex shader 
    "uniform mat4 uMVPMatrix;" + 
    "attribute vec4 vPosition;" + 
    "void main() {" + 
    // the matrix must be included as a modifier of gl_Position 
    " gl_Position = uMVPMatrix * vPosition;" + 
    "}"; 
    
  2. रेंडरर वर्ग में:

    public class MyGL20Renderer implements GLSurfaceView.Renderer { 
    [...] 
    // create a model matrix for the triangle 
    private final float[] mModelMatrix = new float[16]; 
    // create a temporary matrix for calculation purposes, 
    // to avoid the same matrix on the right and left side of multiplyMM later 
    // see https://stackoverflow.com/questions/13480043/opengl-es-android-matrix-transformations#comment18443759_13480364 
    private float[] mTempMatrix = new float[16]; 
    [...] 
    
  3. onDrawFrame में परिवर्तनों को लागू करें, अनुवाद के साथ शुरू:

    public void onDrawFrame(GL10 unused) { 
    [...] 
    Matrix.setIdentityM(mModelMatrix, 0); // initialize to identity matrix 
    Matrix.translateM(mModelMatrix, 0, -0.5f, 0, 0); // translation to the left 
    
  4. फिर रोटेशन:

    // Create a rotation transformation for the triangle 
    long time = SystemClock.uptimeMillis() % 4000L; 
    float mAngle = 0.090f * ((int) time); 
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f); 
    
  5. रोटेशन और अनुवाद, कम्बाइन से बचने "mModelMatrix

    का उपयोग कर सही और की बाईं ओर एक ही मैट्रिक्स के रूप में multiplyMM "(देखें 2)

    // Combine Rotation and Translation matrices 
    mTempMatrix = mModelMatrix.clone(); 
    Matrix.multiplyMM(mModelMatrix, 0, mTempMatrix, 0, mRotationMatrix, 0); 
    
  6. प्रक्षेपण और कैमरे को देखने के साथ मॉडल मैट्रिक्स कम्बाइन; फिर "multiplyMM का सही और बाईं ओर एक ही मैट्रिक्स के रूप में" mModelMatrix

    उपयोग करने से बचें (2 देख)

    // Combine the model matrix with the projection and camera view 
    mTempMatrix = mMVPMatrix.clone(); 
    Matrix.multiplyMM(mMVPMatrix, 0, mTempMatrix, 0, mModelMatrix, 0); 
    
  7. आकार बनाएं

    // Draw shape 
    mTriangle.draw(mMVPMatrix); 
    

सभी को धन्यवाद, सभी उपयोगी इनपुट के लिए मैं इस धागे से आकर्षित कर सकता हूं।

+1

यह पूरी तरह से काम करता है - एकमात्र ट्यूटोरियल जो मैंने पार किया है जिसने मुझे मदद की है। आपके उत्तर के लिए धन्यवाद! – Antinous

+1

यदि यह किसी अन्य व्यक्ति की सहायता करता है जो इस उत्तर में आता है, तो वह हिस्सा जो मेरे लिए स्पष्ट नहीं था वह था कि Matrix.multiplyMM गंतव्य मैट्रिक्स _during_ गणना को संशोधित करता है, इसके बाद नहीं। तो यदि आप रोटेशन द्वारा एमवीपी गुणा करना चाहते हैं, और परिणाम एमवीपी में डालते हैं, तो Matrix.multiplyMM (एमएमवीपीमैट्रिक्स, 0, एमएमवीपीमैट्रिक्स, 0, एमएमडेलमैट्रिक्स, 0) जा रहा है, मक्खी पर एमएमवीपीमैट्रिक्स को म्यूट कर देगा, जिसके परिणामस्वरूप एक अजीब गणना होगी। यही कारण है कि उपरोक्त क्लोन काम करता है। मेरे उद्देश्यों के लिए, मैं दो अलग "स्क्रैच" मैट्रिक्स के बीच फ़्लिप करके "चेन" गणना करने में सक्षम था, उदाहरण के लिए: http://pastebin.com/h7c9Ktg9 –

2

यदि आप आंदोलन देखना चाहते हैं, तो आपको प्रत्येक फ्रेम mtriangle.mAngle अपडेट करना चाहिए (अधिमानतः गति के अंतर या अन्य प्रक्रियाओं के कारण देरी से निपटने के लिए समय के एक समारोह के रूप में ...)।

ध्यान दें कि Matrix.setIdentityM (mModelMatrix, 0); सभी संचित घुमावों और अनुवादों को "शून्य" या वास्तव में पहचान मैट्रिक्स में पुनर्स्थापित करता है ... वही सम्मेलन सेट फ़ंक्शंस पर btw लागू होता है। सभी परिवर्तनों को जमा करने के लिए, किसी को

  • सेटडिडेन्टिटी (मॉडल);
  • अनुवाद (ट्रांस); // रोटेशन की उत्पत्ति
  • घुमाएं (rotmatrix); // रोटेशन
  • अनुवाद (टी 2) जमा करने के लिए; // कुछ बेहतर स्थिति के लिए फिर से अनुवाद करने के लिए ...

इसके अलावा एक-एक कॉल के बीच की वस्तु अनुवाद वेक्टर [बैल, oy, आउंस] मान रखने के लिए और उन्हें Matrix.translateM (mModelMatrix, बैल को खिलाने चाहिए, ओई, ओज, 0);

आम तौर पर एक सब 'का अनुवाद, घुमाने के लिए, पैमाने', आदि मैट्रिक्स को जल्द से जल्द पदानुक्रम एक जटिल कंटेनर से अधिक ऑब्जेक्ट होने और बाउंडिंग बॉक्स होने प्रति, संयोजित और वस्तु प्रति उन्हें कैश, या तो यह है कि एक से अधिक ऑब्जेक्ट हो सकता है कैमरे के पीछे (या आमतौर पर देखने के निराशा के बाहर) जब खींचा।

आमतौर पर एक मैट्रिक्स में एक चलती कैमरा रखता है और प्रति फ्रेम प्रक्षेपण मैट्रिक्स के साथ गुणा करता है।

आप की तरह कुछ के साथ शुरू कर सकते हैं:

float Time = System.currentTimeMillis() * 0.01f; // 10 radians/second == fast! 
Matrix.translateM(mModelMatrix, Math.sin(Time)*2.0f, 0, 1f, 0); 
... 

के रूप में टिम देखा, वहाँ कोई प्रक्षेपण मैट्रिक्स शामिल है जिसका अर्थ है कि सभी z-मान बिल्कुल इस कोड से व्यवहार करते हैं, भले ही बदल रहा है एक्स & y मान बनाना होगा एक अंतर।

मुझे यह कहने का लुत्फ उठाया जाएगा कि एमवीपी मैट्रिक्स का मतलब एम * वी * पी = (एम * वी) * पी = एम * (वी * पी) क्रम में गुणा करना होगा।

+0

मैं यह उल्लेख करना भूल गया कि ड्रॉइंग विधि मेरे EventListener द्वारा ट्रिगर की गई है, इसलिए मुझे लगता है कि मुझे अभी तक फ़ंक्शन की आवश्यकता नहीं है। मेरा त्रिभुज अपेक्षित के रूप में घूमता है। यह सिर्फ अक्ष के साथ नहीं चलता है। –

+0

ऐसा इसलिए है क्योंकि Matrix.rotateM के बजाय यह * setRotate * है। (या जो भी एंड्रॉइड जीएलएस एपीआई में है) –

+0

मेरे पास अब 'Matrix.setIdentityM (mModelMatrix, 0) है; Matrix.setIdentityM (एमएमवीपीमैट्रिक्स, 0); Matrix.translateM (mModelMatrix, 0, 1f, 0f, 0); Matrix.rotateM (mModelMatrix, 0, mTriangle.mAngle, 0, 0, -1.0f); Matrix.multiplyMM (tempMatrix, 0, mVMatrix, 0, mmodelMatrix, 0); Matrix.multiplyMM (एमएमवीपीमैट्रिक्स, 0, mProjMatrix, 0, tempMatrix, 0); 'और अभी भी ज़ेड-एक्सिस के आसपास घूर्णन देखते हैं और कोई अन्य आंदोलन नहीं। वस्तुओं को उत्पत्ति के अनुवाद के साथ टिप के लिए धन्यवाद। ऑब्जेक्ट को मूल से बाहर ले जाने के लिए इसे प्रबंधित करने के बाद मैं इस समस्या को संबोधित करूंगा। –

0

ध्यान दें कि आप अपने प्रक्षेपण मैट्रिक्स को आपके द्वारा खींचे गए त्रिकोण पर लागू नहीं कर रहे हैं, जिससे समस्याएं पैदा हो सकती हैं।

शायद होना चाहिए:

Matrix.multiplyMM(mMVMatrix, 0, mVMatrix, 0, mModelMatrix, 0); 
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVMatrix, 0); 
+0

पहली पंक्ति नहीं होना चाहिए 'Matrix.multiplyMM (mVMatrix, 0, mVMatrix, 0, mmodelMatrix, 0) '? यदि हाँ, मैं अभी भी केवल रोटेशन देख सकता हूं। कोई अनुवाद नहीं। –

+1

AFAIK आपके पास multiplyMM के दाएं और बाएं तरफ एक ही मैट्रिक्स नहीं हो सकता है: * हालांकि, परिणाम तत्व मान अनिर्धारित हैं यदि परिणाम तत्व एलएचएस या rhs तत्वों को ओवरलैप करते हैं। *। मैंने दृश्य मॉडल के अस्थायी परिणाम को पकड़ने के लिए, 'मॉडल व्यू' मैट्रिक्स, वहां एक नया मैट्रिक्स परिभाषित किया है। – Tim

+0

आपके जैसा ही था - एक अस्थायी मैट्रिक्स परिभाषित किया गया। अपेक्षित के रूप में अभी भी एक ही समस्या है। –