Texture not applying to mesh - OpenGL

2019-03-06 18:12发布

问题:

I am using OpenGL Es. I have successfully loaded the obj file (mesh) and its displayed well but when I am applying the texture its not displaying.

I have added the code below.

public void draw(GL10 gl) {
    // bind the previously generated texture
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    // Set the face rotation
    gl.glFrontFace(GL10.GL_CW);

    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    for(int i=0; i<parts.size(); i++){
        TDModelPart t=parts.get(i);
        gl.glNormalPointer(GL10.GL_FLOAT, 0, t.getNormalBuffer());
        gl.glDrawElements(GL10.GL_TRIANGLES,t.getFacesCount(),GL10.GL_UNSIGNED_SHORT,t.getFaceBuffer());
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }
}

public void buildVertexBuffer(){
    ByteBuffer vBuf = ByteBuffer.allocateDirect(v.size() * 4);
    vBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = vBuf.asFloatBuffer();
    vertexBuffer.put(toPrimitiveArrayF(v));
    vertexBuffer.position(0);

    vBuf = ByteBuffer.allocateDirect(texture.length * 4);
    vBuf.order(ByteOrder.nativeOrder());
    textureBuffer = vBuf.asFloatBuffer();
    textureBuffer.put(texture);
    textureBuffer.position(0);
}

private static float[] toPrimitiveArrayF(Vector<Float> vector){
    float[] f;
    f=new float[vector.size()];
    for (int i=0; i<vector.size(); i++){
        f[i]=vector.get(i);
    }
    return f;
}

/**
 * Load the texture for the square
 * @param gl
 * @param context
 */
public void loadGLTexture(GL10 gl, Context context) {
    // loading texture
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
            R.drawable.nehe);

    // generate one texture pointer
    gl.glGenTextures(1, textures, 0);
    // ...and bind it to our array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

    // create nearest filtered texture
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
    //gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    //gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

    // Use Android GLUtils to specify a two-dimensional texture image from our bitmap 
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    // Clean up
    bitmap.recycle();
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbientBuffer);      
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuseBuffer);      
    gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer);    
    gl.glEnable(GL10.GL_LIGHT0);

    model.loadGLTexture(gl, context);
    gl.glEnable(GL10.GL_TEXTURE_2D);
    gl.glShadeModel(GL10.GL_SMOOTH);            
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    
    gl.glClearDepthf(1.0f);                     
    gl.glEnable(GL10.GL_DEPTH_TEST);            
    gl.glDepthFunc(GL10.GL_LEQUAL);         

    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
}

回答1:

//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

for(int i=0; i<parts.size(); i++) {
    TDModelPart t=parts.get(i);
    gl.glNormalPointer(GL10.GL_FLOAT, 0, t.getNormalBuffer());
    gl.glDrawElements(GL10.GL_TRIANGLES,t.getFacesCount(),GL10.GL_UNSIGNED_SHORT,t.getFaceBuffer());
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}

Of course disabling the texCoord array before drawing anything is not a good idea, since that will cause your object to not have any valid texture coordinates (well, stricty speaking all its vertices have the current default texture coordinates). In the same way you shouldn't disable the GL_VERTEX_ARRAY at the end of the loop either, since this will course your object to not have any valid position data for all the following loop iterations. So your code should probably look like:

// bind the previously generated texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Set the face rotation
gl.glFrontFace(GL10.GL_CW);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

for(int i=0; i<parts.size(); i++){
    TDModelPart t=parts.get(i);
    gl.glNormalPointer(GL10.GL_FLOAT, 0, t.getNormalBuffer());
    gl.glDrawElements(GL10.GL_TRIANGLES,t.getFacesCount(),GL10.GL_UNSIGNED_SHORT,t.getFaceBuffer());
}

//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

(For now I'll ignore that you set a glNormalPointer while not enabling the GL_NORMAL_ARRAY.)

Always keep in mind that OpenGL is a state machine and all operations, especially draw calls, operate on the current state at the point they are called and that state won't ever change except you change it yourself (with "you" meaning the application code here, including any other thrid party components using the same OpenGL context).