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

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

 

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

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

主活动类代码如下:

import android.app.Activity;
import android.os.Bundle;

public class GL10JNIActivity extends Activity {

	private GL10JNIView mView;

	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		mView = new GL10JNIView(this);
		setContentView(mView);
	}

	@Override
	protected void onPause() {
		super.onPause();
		mView.onPause();
	}

	@Override
	protected 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) {

	}
	
	@Override
	public void onDrawFrame(GL10 gl) {
		
		GL10JNILib.step();
		
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		GL10JNILib.resize(width, height);
	}

	@Override
	public 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    := libgl10jni
LOCAL_CFLAGS    := -Werror
LOCAL_SRC_FILES := gl_code.cpp
LOCAL_LDLIBS    := -llog -lGLESv1_CM

include $(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 应用程序即可。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值