[Android NDK]Android JNI開發例子 ---3 在JNI中實現openGL功能
阿新 • • 發佈:2019-02-03
這個例子使用native部分來實現opengl es而不是java部分。
Java部分與例子2相似。
MainActivity.java
public class MainActivity extends Activity { GLSurfaceView mGLView; static { System.loadLibrary("myegl_jni"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // (NEW) this.mGLView = new MyGLSurfaceView(this); setContentView(this.mGLView); } }
MyGLSurfaceView.java
Renderer.javapublic class MyGLSurfaceView extends GLSurfaceView { GLSurfaceView.Renderer mRenderer; private boolean goNative; /** * TODO Put here a description of what this constructor does. * * @param context * @param goNative */ public MyGLSurfaceView(Context context) { super(context); // TODO Auto-generated constructor stub. mRenderer = new MyRenderer(); // Set the Renderer for drawing on the GLSurfaceView setRenderer(mRenderer); } }
public class MyRenderer implements GLSurfaceView.Renderer { private static final String TAG = "agl"; private native String nativeGetHelloString(); private native void nativeDrawFrame(); private native void nativeSurfaceChanged(int width, int height); private native void nativeSurfaceCreated(); @Override public void onDrawFrame(GL10 gl) { nativeDrawFrame(); Log.d(TAG, "onDrawFrame " + nativeGetHelloString()); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { nativeSurfaceChanged(width,height); Log.d(TAG, "onSurfaceChanged"); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { nativeSurfaceCreated(); Log.d(TAG, "onSurfaceCreate"); } }
在jni資料夾內建立include資料夾。 在include下建立一個頭檔案。cpp中的所有變數和函式要在宣告之後才能夠直接使用。 .h檔案中都是宣告。
#include <jni.h>
#include <string.h>
#include <android/log.h>
#include <GLES/gl.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
extern "C" {
#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__)
#define LOGD(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
void printGLString(char* name, GLenum s);
void init();
void resize(int width, int height);
void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
void renderFrame();
GLfloat rtri; //三角形的旋轉變數
GLfloat rquad; //四邊形的旋轉變數
const GLfloat PI = 3.1415f;
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
};
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
};
} //end of extern "C"
cpp檔案
#include "com_example_nativeegl_MyRenderer.h"
extern "C" {
void printGLString(char* name, GLenum s) {
char *v = (char *) glGetString(s);
LOGI("GL %s = %s", name, v);
}
/*
* Class: com_example_nativeegl_MyRenderer
* Method: nativeGetHelloString
* Signature: ()Ljava/lang/String;
*/
jstring nativeGetHelloString(JNIEnv *env, jobject obj) {
return env->NewStringUTF((char*)" This is calling from JNI suckers!");
}
/*
* Class: com_example_nativeegl_MyRenderer
* Method: nativeDrawFrame
* Signature: ()V
*/
void nativeDrawFrame(JNIEnv *env, jobject obj) {
renderFrame();
}
/*
* Class: com_example_nativeegl_MyRenderer
* Method: nativeSurfaceChanged
* Signature: (II)V
*/
void nativeSurfaceChanged(JNIEnv *env, jobject obj, jint width, jint height){
resize(width, height);
}
void init() {
LOGD("init the renderer");
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);
}
void resize(int width, int height) {
LOGD("resize the renderer");
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 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 renderFrame() {
LOGD("renderFrame the renderer");
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();
}
/*
* Class: com_example_nativeegl_MyRenderer
* Method: nativeSurfaceCreated
* Signature: ()V
*/
void nativeSurfaceCreated(JNIEnv *env, jobject obj) {
init();
}
//----------------------------JNI part:Native register------------------------------------------------------
static JNINativeMethod gMethods[] = {
//{"native method name from Java","(arguments type)return type", "(void*)local_native_name"
{"nativeGetHelloString", "()Ljava/lang/String;", (void *)nativeGetHelloString},
{"nativeDrawFrame", "()V", (void *)nativeDrawFrame},
{"nativeSurfaceChanged", "(II)V", (void *)nativeSurfaceChanged},
{"nativeSurfaceCreated", "()V", (void *)nativeSurfaceCreated},
};
static const char* className="com/example/nativeegldynamicjni/MyRenderer";
static int registerNativeMethods(JNIEnv *env) {
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL) {
LOGD("failed to load the class %s", className);
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
} //end of registerNativeMethods
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
LOGE("ERROR: GetEnv failed\n");
goto bail;
}
if (registerNativeMethods(env) < 0) {
LOGE("ERROR: jnitest native registration failed\n");
goto bail;
}
result = JNI_VERSION_1_4;
bail:
return result;
}
} //end of extern "C"
Android.mk
#Description:makefile of Helloworld
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS := -Wall
LOCAL_MODULE := myegl_jni
LOCAL_C_INCLUDES :=$(LOCAL_PATH)/include
LOCAL_CPP_EXTENSION := .cpp
LOCAL_LDLIBS += -llog -lGLESv1_CM
LOCAL_SRC_FILES := com_example_nativeegl_MyRenderer.cpp
include $(BUILD_SHARED_LIBRARY)
在專案根目錄想執行ndk-build編譯jni出.so庫。