采用JNI方法利用opengl es 1.x在android上绘图

来源:互联网 发布:软件项目质量计划 编辑:程序博客网 时间:2024/05/16 11:38

我们可以在jni层上编写opengl代码, 进行3d 图形的绘制,下面这个例子就是在一个绘制四面体的例子, 实例的绘制代码是在jni层实现的, 采用c++语言编写。

 

1. 首先, 创建上层应用程序相关类, 组织好调用路径。

     这里主要是创建活动类, 渲染类以及相关辅助类。

主活动类代码如下:

import android.app.Activity;import android.os.Bundle;public class GL10JNIActivity extends Activity {private GL10JNIView mView;@Overrideprotected void onCreate(Bundle icicle) {super.onCreate(icicle);mView = new GL10JNIView(this);setContentView(mView);}@Overrideprotected void onPause() {super.onPause();mView.onPause();}@Overrideprotected void onResume() {super.onResume();mView.onResume();}}


其次创建opengl视图类,代码如下:

import android.content.Context;import android.opengl.GLSurfaceView;public class GL10JNIView extends GLSurfaceView {private static final String LOG_TAG = GL10JNIView.class.getSimpleName();private MyRenderer myRenderer;public GL10JNIView(Context context) {super(context);setEGLConfigChooser(8, 8, 8, 8, 16, 0);myRenderer = new MyRenderer(context);setRenderer(myRenderer);}}


接着创建渲染类,代码如下:

import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.content.Context;import android.opengl.GLSurfaceView.Renderer;public class MyRenderer implements Renderer {public MyRenderer(Context ctx) {}@Overridepublic void onDrawFrame(GL10 gl) {GL10JNILib.step();}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {GL10JNILib.resize(width, height);}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {GL10JNILib.init();}}


最后,声明与jni 相对应的本地化方法, 加载相应的jni代码生成的库, 代码如下:

public class GL10JNILib {    static {        System.loadLibrary("gl10jni");    }   /**    * @param width the current view width    * @param height the current view height    */    public static native void resize(int width, int height);    public static native void step();    public static native void init();}


2. 编写jni绘制代码

在android工程的根目录下创建jni 文件夹, 新建两个文件, 一个是Android.mk文件,另一个就是我们实现绘制的代码文件,其中Android.mk文件的内容如下:

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := libgl10jniLOCAL_CFLAGS    := -WerrorLOCAL_SRC_FILES := gl_code.cppLOCAL_LDLIBS    := -llog -lGLESv1_CMinclude $(BUILD_SHARED_LIBRARY)


最后是相应的绘制代码,如下所示:

#include <jni.h>#include <android/log.h>#include <GLES/gl.h>#include <GLES/glext.h>#include <stdio.h>#include <stdlib.h>#include <math.h>#define  LOG_TAG    "libgl2jni"#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)static void printGLString(const char *name, GLenum s) {    const char *v = (const char *) glGetString(s);    LOGI("GL %s = %s\n", name, v);}static void checkGlError(const char* op) {    for (GLint error = glGetError(); error; error            = glGetError()) {        LOGI("after %s() glError (0x%x)\n", op, error);    }}bool init() {    printGLString("Version", GL_VERSION);    printGLString("Vendor", GL_VENDOR);    printGLString("Renderer", GL_RENDERER);    printGLString("Extensions", GL_EXTENSIONS);    glShadeModel(GL_SMOOTH);// 启用阴影平滑    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);// 黑色背景    glClearDepthf(1.0f);// 设置深度缓存    glEnable(GL_DEPTH_TEST);// 启用深度测试    glDepthFunc(GL_LEQUAL);// 所作深度测试的类型    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// 告诉系统对透视进行修正    return true;}const GLfloat gVertices[] = {0.0f, 1.0f, 0.0f,-1.0f,-1.0f, 1.0f,1.0f,-1.0f, 1.0f,0.0f, 1.0f, 0.0f,1.0f,-1.0f, 1.0f,1.0f,-1.0f, -1.0f,0.0f, 1.0f, 0.0f,1.0f,-1.0f, -1.0f,-1.0f,-1.0f, -1.0f,0.0f, 1.0f, 0.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, 1.0f};const GLfloat gColors[] = {1.0f,0.0f,0.0f, 1.0f,0.0f,1.0f,0.0f, 1.0f,0.0f,0.0f,1.0f, 1.0f,1.0f,0.0f,0.0f, 1.0f,0.0f,0.0f,1.0f, 1.0f,0.0f,1.0f,0.0f, 1.0f,1.0f,0.0f,0.0f, 1.0f,0.0f,1.0f,0.0f, 1.0f,0.0f,0.0f,1.0f, 1.0f,1.0f,0.0f,0.0f, 1.0f,0.0f,0.0f,1.0f, 1.0f,0.0f,1.0f,0.0f, 1.0f};static GLfloat rtri;  //三角形的旋转变量static GLfloat rquad;  //四边形的旋转变量const GLfloat PI = 3.1415f;static void _gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar){GLfloat top = zNear * ((GLfloat) tan(fovy * PI / 360.0));GLfloat bottom = -top;GLfloat left = bottom * aspect;GLfloat right = top * aspect;glFrustumf(left, right, bottom, top, zNear, zFar);}void resize(int width, int height){    if (height==0)// 防止被零除      {              height=1;// 将Height设为1      }      glViewport(0, 0, width, height);// 重置当前的视口      glMatrixMode(GL_PROJECTION);// 选择投影矩阵      glLoadIdentity();// 重置投影矩阵      GLfloat ratio = (GLfloat)width/(GLfloat)height;      // 设置视口的大小      _gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);  //    glOrthof(-2.0f, 2.0f, -2.0f, 2.0f, -2.0f, 2.0f);      glMatrixMode(GL_MODELVIEW);// 选择模型观察矩阵      glLoadIdentity();// 重置模型观察矩阵}void renderFrame() {    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 清除屏幕及深度缓存    glLoadIdentity();// 重置模型观察矩阵    glTranslatef(0.0f,0.0f, -6.0f);// 移入屏幕 6.0    glRotatef(rtri,0.0f,1.0f,0.0f);// 绕Y轴旋转金字塔    glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_COLOR_ARRAY);    glColorPointer(4, GL_FLOAT, 0, gColors);    glVertexPointer(3, GL_FLOAT, 0, gVertices);    glDrawArrays(GL_TRIANGLES, 0, 12);rtri += 0.2f;// 增加三角形的旋转变量//LOGI("xxxxx");glDisableClientState(GL_VERTEX_ARRAY);glDisableClientState(GL_COLOR_ARRAY);glFlush();}extern "C" {    JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_resize(JNIEnv * env, jobject obj,  jint width, jint height);    JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_step(JNIEnv * env, jobject obj);    JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_init(JNIEnv * env, jobject obj);};JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_resize(JNIEnv * env, jobject obj,  jint width, jint height){    resize(width, height);}JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_step(JNIEnv * env, jobject obj){    renderFrame();}JNIEXPORT void JNICALL Java_com_test_fuyajun_GL10JNILib_init(JNIEnv * env, jobject obj){init();}


利用ndk-build工具将jni代码编译成库, 然后运行android 应用程序即可。