2012-04-25 56 views
0

我有問題將OpenGL座標正確映射到我的android屏幕。出於某種原因,x座標不包含在屏幕內。當我嘗試在半屏幕半徑的屏幕中間畫一個圓時,這是可見的。該圓應該足夠大以適合屏幕的x邊界,但是它會超出屏幕邊界,實際上是觸摸屏幕的y邊界。同樣,如果我告訴要在0,0(左上角)繪製的圓,中心實際上會在將其轉換爲OpenGL座標後繪製在x邊界之外。OpenGL沒有將座標正確映射到android屏幕

希望有道理。

這裏是我的DrawScreen類:

public class DrawScreen implements GLSurfaceView.Renderer { 

Ball ball; 

public float mAngle; 

private int mProgram; 
private int maPositionHandle; 

private int muMVPMatrixHandle; 
private float[] mMVPMatrix = new float[16]; 
private float[] mVMatrix = new float[16]; 
private float[] mProjMatrix = new float[16]; 

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; \n" + 

     "attribute vec4 vPosition; \n" + 
     "void main(){    \n" + 

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

     "} \n"; 

private final String fragmentShaderCode = 
     "precision mediump float; \n" + 
       "void main(){    \n" + 
       " gl_FragColor = vec4 (0.63671875, 0.76953125, 0.22265625, 1.0); \n" + 
       "}       \n"; 


public void onSurfaceCreated(GL10 unused, EGLConfig config) { 

    ball = new Ball(); 

    // Set the background frame color 
    GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); 

    ball.initShapes(240, 360, 240); 

    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); 
    int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); 

    mProgram = GLES20.glCreateProgram();    // create empty OpenGL Program 
    GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program 
    GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program 
    GLES20.glLinkProgram(mProgram);     // creates OpenGL program executables 

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

} 

public void onDrawFrame(GL10 unused) { 

    // Redraw background color 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 

    // Add program to OpenGL environment 
    GLES20.glUseProgram(mProgram); 

    // Prepare the circle data 
    GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 12, ball.ballVB); 
    GLES20.glEnableVertexAttribArray(maPositionHandle); 

    // Apply a ModelView Projection transformation 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0); 
    GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 

    // Draw the circle 
    GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 0, (int) ball.getNumSeg()); 

} 

public void onSurfaceChanged(GL10 unused, int width, int height) { 
    // Set the OpenGL viewport to the same size as the surface. 
    GLES20.glViewport(0, 0, width, height); 

    // Create a new perspective projection matrix. The height will stay the same 
    // while the width will vary as per aspect ratio. 
    final float ratio = (float) width/height; 
    final float left = ratio; 
    final float right = -ratio; 
    final float bottom = 1.0f; 
    final float top = -1.0f; 
    final float near = 3.0f; 
    final float far = 7.0f; 

    //Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far); 

    Matrix.orthoM(mProjMatrix, 0, left, right, bottom, top, near, far);  

    muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 

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

} 


private int loadShader(int type, String shaderCode){ 

    // create a vertex shader type (GLES20.GL_VERTEX_SHADER) 
    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) 
    int shader = GLES20.glCreateShader(type); 

    // add the source code to the shader and compile it 
    GLES20.glShaderSource(shader, shaderCode); 
    GLES20.glCompileShader(shader); 

    return shader; 

} 

這裏的地方我轉換屏幕座標OpenGL的座標:

float numSegments = 360; 

public void initShapes(float tx, float ty, float tr){ 

    cx = (tx/(480/2)) - 1.f; 
    cy = (ty/(720/2)) - 1.f; 

    r = (tr/(480/2)) ; 

    System.out.println(r); 
    System.out.println(cx); 
    System.out.println(cy); 

    float ballCoords[] = new float[(int) (numSegments * 3)]; 

    double theta = (2 * 3.1415926/numSegments); 
    float c = (float) Math.cos(theta);//precalculate the sine and cosine 
    float s = (float) Math.sin(theta); 
    float t; 

    float x = r;//we start at angle = 0 
    float y = 0; 

    for(int i = 0; i < (numSegments * 3); i = i + 3) { 

     ballCoords[i] = (x + cx); 
     ballCoords[i + 1] = (y + cy); 
     ballCoords[i + 2] = (0); 

     //apply the rotation matrix 
     t = x; 
     x = c * x - s * y; 
     y = s * t + c * y; 

    } 

    // initialize vertex Buffer for triangle 
    ByteBuffer vbb = ByteBuffer.allocateDirect(
      // (# of coordinate values * 4 bytes per float) 
      ballCoords.length * 4); 
    vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order 
    ballVB = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer 
    ballVB.put(ballCoords); // add the coordinates to the FloatBuffer 
    ballVB.position(0);   // set the buffer to read the first coordinate 

} 

回答

0

好了,我解決它...雖然它看起來並不漂亮。

我基本上把onSurfaceChanged中的所有數字都放在頭上,它看起來就是我現在想要的方式。

這是我的新代碼:

public void onSurfaceChanged(GL10 unused, int width, int height) { 
    // Set the OpenGL viewport to the same size as the surface. 
    GLES20.glViewport(0, 0, width, height); 

    // Create a new perspective projection matrix. The height will stay the same 
    // while the width will vary as per aspect ratio. 
    final float ratio = (float) height/width; 
    final float left = 1; 
    final float right = -1; 
    final float bottom = ratio; 
    final float top = -ratio; 
    final float near = 3.0f; 
    final float far = 7.0f; 

    //Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far); 

    Matrix.orthoM(mProjMatrix, 0, left, right, bottom, top, near, far);  

    muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 

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

} 
+0

哇,談論爲時過早〜現在我有同樣的錯誤,但在相反的。 X工作正常,但是如果我將y設置爲0,而不是一直到頂部。 – 2012-04-26 22:35:56