簡體   English   中英

Android OpenGL ES環境中的插值

[英]Interpolation in Android OpenGL ES Environment

在嘗試為測試動畫設置游戲循環線程時,我遇到了一些問題。 在啟動過程中顯示錯誤,並且Android程序在啟動屏幕中運行,但隨后終止。 這是紅色突出顯示的Logcat錯誤。

09-24 16:09:18.731: E/AndroidRuntime(569): FATAL EXCEPTION: GLThread 76
09-24 16:09:18.731: E/AndroidRuntime(569): java.lang.NullPointerException
09-24 16:09:18.731: E/AndroidRuntime(569):  at 
com.spacewrecksoftware.iceward.GLrenderer.onSurfaceCreated(GLrenderer.java:22)
09-24 16:09:18.731: E/AndroidRuntime(569):  at 
android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1446)
09-24 16:09:18.731: E/AndroidRuntime(569):  at 
android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216)

該程序使用插值渲染的測試實現來創建在橫向屏幕上來回移動的紋理,以便在更高的幀頻下實現更流暢的動畫。 這是按順序排列的游戲循環,渲染器,菜單,對象和狀態文件。

GameLoop:

import android.os.SystemClock;

public class GameLoop extends Thread {
public static int deltaTime;
boolean gameRunning = true;
public void setRunning(boolean running) {
    this.gameRunning = running;
}
public ObjectState previous= new ObjectState(0, 0, 10/1000, 0);
public ObjectState current= new ObjectState(0, 0, 10/1000, 0);
public Globject button= new Globject(previous, current);
public void run() {

    int ticksPerSec = 30;
    int skipTicks = 1000 / ticksPerSec;
    int maxFrameskip = 5;
    long nextGameTick = SystemClock.uptimeMillis();
    int loops;
    long interpolation;
    long oldTimeSinceStart = 0;

    while (gameRunning) {


        loops = 0;
        while( SystemClock.uptimeMillis() > nextGameTick & loops < maxFrameskip){
            long timeSinceStart = SystemClock.uptimeMillis();
              deltaTime = (int) (timeSinceStart - oldTimeSinceStart);
             oldTimeSinceStart = timeSinceStart;
            updateGame();
             nextGameTick += skipTicks;
                loops++;
            }
        interpolation = SystemClock.uptimeMillis() + skipTicks - nextGameTick 
                /  skipTicks ;
        drawGame(interpolation);
    }
}
int switchit = 1;
private void updateGame() {
    if (switchit==1){   
        if (button.now.position_x<=-10){        
             switchit=0;
             button.past.velocity_x=0-button.past.velocity_x;
        }
        else{
    button.past=button.now.copy(button.now);
    button.now=button.past.addDt(button.past, deltaTime);
        }
    }
    else if(switchit==0){   
        if (button.now.position_x>=10){     
             switchit=1;
             button.past.velocity_x=0-button.past.velocity_x;
        }
        else{
            button.past=button.now.copy(button.now);
            button.now=button.past.addDt(button.past, deltaTime);
        }
    }

}
private void drawGame(float interpolation) {
    button.past=button.past.interpolate(button.past, button.now, interpolation);
    Menu.menuSurface.requestRender();

}
}

渲染器:

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;


public class GLrenderer implements Renderer {

private Globject object1;   
private Context context;
long startTime;
public GLrenderer(Context context) {
    this.context = context;
    object1 = new Globject(null, null);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {       
    //Load the texture for the cube once during Surface creation
    object1.now.position_x=0;
    object1.past.position_x=0;
    object1.loadGLTexture(gl, this.context);
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
    gl.glEnable(GL10.GL_TEXTURE_2D);            //Enable Texture Mapping
    gl.glShadeModel(GL10.GL_SMOOTH);            //Enable Smooth Shading
    gl.glClearColor(0.0f, 0.666f, 0.831f, 1f); 
    gl.glClearDepthf(1.0f);                     //Depth Buffer Setup
    gl.glEnable(GL10.GL_DEPTH_TEST);            //Enables Depth Testing
    gl.glDepthFunc(GL10.GL_LEQUAL);             //The Type Of Depth Testing To Do

    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
}
/**
 * Here we do our drawing
 */
public void onDrawFrame(GL10 gl) {
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    
    gl.glLoadIdentity();        

    gl.glTranslatef(0.0f, 0.0f, -20f);  
    gl.glPushMatrix();
    gl.glTranslatef( object1.past.position_x, 0, 0);    
    object1.draw(gl);
    gl.glPopMatrix();

}

/**
 * If the surface changes, reset the view
 */
public void onSurfaceChanged(GL10 gl, int width, int height) {
    if(height == 0) {                       //Prevent A Divide By Zero By
        height = 1;                         //Making Height Equal One
    }

    gl.glViewport(0, 0, width, height);     //Reset The Current Viewport
    gl.glMatrixMode(GL10.GL_PROJECTION);    //Select The Projection Matrix
    gl.glLoadIdentity();                    //Reset The Projection Matrix

    //Calculate The Aspect Ratio Of The Window
    GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);

    gl.glMatrixMode(GL10.GL_MODELVIEW);     //Select The Modelview Matrix
    gl.glLoadIdentity();                    //Reset The Modelview Matrix
}
}

菜單:

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class Menu extends Activity
{
static GLSurfaceView menuSurface;
private GameLoop thread;
@Override
public void onCreate(Bundle savedInstanceState) 
{

    super.onCreate(savedInstanceState);
    menuSurface = new GLSurfaceView(this);
        menuSurface.setRenderer(new GLrenderer(this));
        menuSurface.setRenderMode(0);
    setContentView(menuSurface);
    thread = new GameLoop();
    thread.setRunning(true);
    thread.start();
}

@Override
protected void onResume() 
{
    super.onResume();
    menuSurface.onResume();
}

@Override
protected void onPause() 
{   
    super.onPause();
    menuSurface.onPause();
}   
public boolean onTouchEvent(MotionEvent event) {
            return super.onTouchEvent(event);   
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry) {
    try {
        thread.join();
        retry = false;
    } catch (InterruptedException e) {
        // try again shutting down the thread
    }
}
}
}

對象:注意-圖像是2的冪,四乘一紋理。

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

public class Globject {

private FloatBuffer vertexBuffer;

private FloatBuffer textureBuffer;

private ByteBuffer indexBuffer;


private int[] textures = new int[1];
public ObjectState past;
public ObjectState now;

private float vertices[] = {
                    //Vertices according to faces
                    -4.0f, 1.0f,  //Vertex 0
                    -4.0f, -1.0f,  //v1
                    4.0f, 1.0f,   //v2
                    4.0f, -1.0f   //v3

                                        };

/** The initial texture coordinates (u, v) */   
private float texture[] = {         
                    //Mapping coordinates for the vertices  
                    0.0f, 0.0f,
                    0.0f, 1.0f,             
                    1f, 0.0f,
                    1f, 1.0f


                                        };

/** The initial indices definition */   
private byte indices[] = {

        0,1,2,3             
                                        };

public Globject(ObjectState past2,ObjectState now2) {

    now=now2;
    past=past2;

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

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

    //
    indexBuffer = ByteBuffer.allocateDirect(indices.length);
    indexBuffer.put(indices);
    indexBuffer.position(0);
}

public void draw(GL10 gl) {
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

    //Point to our buffers
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    //Set the face rotation
    gl.glFrontFace(GL10.GL_CW);

    //Enable the vertex and texture state
    gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    //Draw the vertices as triangles, based on the Index Buffer information
    gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);

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

public void loadGLTexture(GL10 gl, Context context) {
    //Get the texture from the Android resource directory
    InputStream is = context.getResources().openRawResource(R.drawable.custom_button1);
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeStream(is);

    } finally {
        //Always clear and close
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }

    //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_LINEAR);
    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 the 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 class ObjectState {
public float position_x;
public float position_y;
public float velocity_x;
public float velocity_y;
public ObjectState(float position_x2, float position_y2, float velocity_x2, float velocity_y2) {
    position_x = position_x2;
    position_y = position_y2;
    velocity_x = velocity_x2;
    velocity_y = velocity_y2;
}
public ObjectState copy(ObjectState state0) {
ObjectState state1= new ObjectState(state0.position_x, state0.position_y,
        state0.velocity_x, state0.velocity_y);
return state1;
}  
public ObjectState subtract(ObjectState state, ObjectState state1){
    ObjectState  state2=state.copy(state);
    state2.position_x=(state1.position_x-state.position_x);
    state2.position_y=(state1.position_y-state.position_y);
    state2.velocity_x=(state1.velocity_x-state.velocity_x);
    state2.velocity_y=(state1.velocity_y-state.velocity_y);
return state2;
}
public ObjectState addDt(ObjectState state, int deltaTime){
    ObjectState  state1=state.copy(state);
    state1.position_x=(state1.velocity_x*deltaTime)+state1.position_x;
    state1.position_y=(state1.velocity_y*deltaTime)+state1.position_y;
return state1;
}
public ObjectState interpolate(ObjectState state, ObjectState state2,float interpolate){
    ObjectState  state1=state.copy(state);
    state1.position_x=(state1.subtract(state2, state).position_x*interpolate)+state.position_x;
    state1.position_y=(state1.subtract(state2, state).position_y*interpolate)+state.position_y;
    state1.velocity_x=(state1.subtract(state2, state).velocity_x*interpolate)+state.velocity_x;
    state1.velocity_y=(state1.subtract(state2, state).velocity_y*interpolate)+state.velocity_y;
return state1;
}
}

我還沒有找到問題,非常感謝您的幫助! 謝謝!

這是一個空指針異常。

GLrenderer構造函數中,您具有以下內容:

object1 = new Globject(null, null);

在您的GLobject代碼中:

public Globject(ObjectState past2,ObjectState now2) {

    now=now2;
    past=past2;
    //...

然后回到GLRenderer您將:

public void onSurfaceCreated(GL10 gl, EGLConfig config) {       
    //Load the texture for the cube once during Surface creation
    object1.now.position_x=0;
    object1.past.position_x=0;

nowpast仍然為空。 需要先分配它們,然后才能訪問它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM