Drawing on android with opengl es 1.x using JNI method

Keywords: Android

Links to the original text: https://my.oschina.net/fuyajun1983cn/blog/263808

We can write opengl code on jni layer and draw 3d graphics. The following example is an example of drawing tetrahedron. The drawing code of the example is implemented on jni layer and is written in c + + language.

 

1. First, create the upper application related classes and organize the call paths.

This is mainly about creating activity classes, rendering classes and related auxiliary classes.

The main activity class code is as follows:

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();
	}
}


Next, create the opengl view class with the following code:

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);
	}
}


Next, create the rendering class with the following code:

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();
	}
	


}


Finally, the localization method corresponding to jni is declared, and the corresponding library generated by jni code is loaded. The code is as follows:

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. Write jni drawing code

Create a jni folder under the root directory of the android project. Create two new files, one is the Android.mk file, and the other is the code file we draw. The contents of the Android.mk file are as follows:

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)


Finally, the corresponding drawing code, as follows:

#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);						// Enable shadow smoothing
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);					// Black background
    glClearDepthf(1.0f);							// Setting Depth Cache
    glEnable(GL_DEPTH_TEST);						// Enable depth testing
    glDepthFunc(GL_LEQUAL);							// Types of in-depth testing
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Tell the system to correct perspective

    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;  //Rotating variables of triangles
static GLfloat rquad;  //Rotating Variables of Quadrilateral

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)								// Prevent being divided by zero
      {
              height=1;							// Set Height to 1
      }

      glViewport(0, 0, width, height);					// Reset the current viewport
      glMatrixMode(GL_PROJECTION);						// Selective Projection Matrix
      glLoadIdentity();							// Reset projection matrix

      GLfloat ratio = (GLfloat)width/(GLfloat)height;
      // Set Size of Viewport
      _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);						// Selecting Model Observation Matrix
      glLoadIdentity();							// Resetting Model Observation Matrix
}

void renderFrame() {

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear screen and deep cache
    glLoadIdentity();					// Resetting Model Observation Matrix
    glTranslatef(0.0f,0.0f, -6.0f);				// Move into screen 6.0

    glRotatef(rtri,0.0f,1.0f,0.0f);				// Revolving around Y axis in Pyramid

    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;						// Increase the rotation variable of the triangle
	//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();
}


jni code is compiled into a library by using ndk-build tool, and then the android application is run.

 

Reproduced in: https://my.oschina.net/fuyajun1983cn/blog/263808

Posted by Lucky_PHP_MAN on Thu, 03 Oct 2019 18:29:15 -0700