vistaでandroid studio その25

# 概要
vistaでandroid studio 1.1.0やってみた。
jniやってみた。
練習問題やってみた。

# 練習問題
jniでopenglでコンパイル済みライブラリーを使え。

# 方針

- ライブラリーは、assimp使う。
- ndk-build使う。

# 写真

![device-2022-09-18-055504.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/fbfae074-a664-d4e2-5d3a-42352e742a9a.png)


# Android.mk

```

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE:= libassimp1
LOCAL_SRC_FILES:= $(LOCAL_PATH)/../externals/assimp-3.0/libs/armeabi-v7a/libassimp.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../externals/assimp-3.0/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := hello2
LOCAL_SRC_FILES := assimp.cpp Matrix.cpp
LOCAL_SHARED_LIBRARIES := libassimp1
LOCAL_LDLIBS := -llog -lGLESv2
include $(BUILD_SHARED_LIBRARY)

```

# Application.mk

```


APP_ABI := armeabi-v7a
APP_PLATFORM := android-21
APP_STL := c++_static

```

# cソース

```
#include <jni.h>
#include <android/log.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include "Matrix.h"
#include <assimp/cimport.h>
#include <assimp/scene.h>
#include <vector>

const struct aiScene * scene = NULL;
std::vector<GLfloat> vertices;
std::vector<GLushort> indices;
#define LOG_TAG "ohi"
#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 const char  glVertexShader[] =
		"attribute vec4 vertexPosition;\n"
		"attribute vec3 vertexColour;\n"
		"varying vec3 fragColour;\n"
		"uniform mat4 projection;\n"
		"uniform mat4 modelView;\n"
		"void main()\n"
		"{\n"
		"	gl_Position = projection * modelView * vertexPosition;\n"
		"	fragColour = vertexColour;\n"
		"}\n";
static const char  glFragmentShader[] =
		"precision mediump float;\n"
		"varying vec3 fragColour;\n"
		"void main()\n"
		"{\n"
		"	gl_FragColor = vec4(fragColour, 1.0);\n"
		"}\n";
GLuint loadShader(GLenum shaderType, const char * shaderSource) {
	GLuint shader = glCreateShader(shaderType);
	if (shader != 0)
	{
		glShaderSource(shader, 1, &shaderSource, NULL);
		glCompileShader(shader);
		GLint compiled = 0;
		glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
		if (compiled != GL_TRUE)
		{
			GLint infoLen = 0;
			glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
			if (infoLen > 0)
			{
				char * logBuffer = (char *) malloc(infoLen);
				if (logBuffer != NULL)
				{
					glGetShaderInfoLog(shader, infoLen, NULL, logBuffer);
					LOGE("Could not Compile Shader %d:\n%s\n", shaderType, logBuffer);
					free(logBuffer);
					logBuffer = NULL;
				}
				glDeleteShader(shader);
				shader = 0;
			}
		}
	}
	return shader;
}
GLuint createProgram(const char * vertexSource, const char * fragmentSource) {
	GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource);
	if (vertexShader == 0)
	{
		return 0;
	}
	GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
	if (fragmentShader == 0)
	{
		return 0;
	}
	GLuint program = glCreateProgram();
	if (program != 0)
	{
		glAttachShader(program, vertexShader);
		glAttachShader(program, fragmentShader);
		glLinkProgram(program);
		GLint linkStatus = GL_FALSE;
		glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
		if(linkStatus != GL_TRUE)
		{
			GLint bufLength = 0;
			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
			if (bufLength > 0)
			{
				char * logBuffer = (char *) malloc(bufLength);
				if (logBuffer != NULL)
				{
					glGetProgramInfoLog(program, bufLength, NULL, logBuffer);
					LOGE("Could not link program:\n%s\n", logBuffer);
					free(logBuffer);
					logBuffer = NULL;
				}
			}
			glDeleteProgram(program);
			program = 0;
		}
	}
	return program;
}
GLuint glProgram;
GLuint vertexLocation;
GLuint vertexColourLocation;
GLuint projectionLocation;
GLuint modelViewLocation;
float projectionMatrix[16];
float modelViewMatrix[16];
float angle = 0;
bool setupGraphics(int width, int height) {
	glProgram = createProgram(glVertexShader, glFragmentShader);
	if (glProgram == 0)
	{
		LOGE ("Could not create program");
		return false;
	}
	vertexLocation = glGetAttribLocation(glProgram, "vertexPosition");
	vertexColourLocation = glGetAttribLocation(glProgram, "vertexColour");
	projectionLocation = glGetUniformLocation(glProgram, "projection");
	modelViewLocation = glGetUniformLocation(glProgram, "modelView");
	matrixPerspective(projectionMatrix, 45, (float) width / (float) height, 0.1f, 100);
	glEnable(GL_DEPTH_TEST);
	glViewport(0, 0, width, height);
	std::string sphere = "s 0 0 0 10";
	scene = aiImportFileFromMemory(sphere.c_str(), sphere.length(), 0, ".nff");
	if (!scene)
	{
		LOGE("Open Asset Importer could not load scene. \n");
		return false;
	}
	int vertices_accumulation = 0;
	for (int i = 0; i < scene->mNumMeshes; i++)
	{
		for (int j = 0; j < scene->mMeshes[i]->mNumVertices; j++)
		{
			const aiVector3D& vector = scene->mMeshes[i]->mVertices[j];
			vertices.push_back(vector.x);
			vertices.push_back(vector.y);
			vertices.push_back(vector.z);
		}
		for (unsigned int j = 0 ; j < scene->mMeshes[i]->mNumFaces ; j++)
		{
			const aiFace& face = scene->mMeshes[i]->mFaces[j];
			indices.push_back(face.mIndices[0] + vertices_accumulation);
			indices.push_back(face.mIndices[1] + vertices_accumulation);
			indices.push_back(face.mIndices[2] + vertices_accumulation);
		}
		vertices_accumulation += scene->mMeshes[i]->mNumVertices;
	}
	return true;
}
void renderFrame() {
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
	matrixIdentityFunction(modelViewMatrix);
	matrixRotateX(modelViewMatrix, angle);
	matrixRotateY(modelViewMatrix, angle);
	matrixTranslate(modelViewMatrix, 0.0f, 0.0f, -10.0f);
	glUseProgram(glProgram);
	glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
	glEnableVertexAttribArray(vertexLocation);
	glVertexAttribPointer(vertexColourLocation, 3, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
	glEnableVertexAttribArray(vertexColourLocation);
	glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix);
	glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, modelViewMatrix);
	glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, &indices[0]);
	angle += 1;
	if (angle > 360)
	{
		angle -= 360;
	}
}
extern "C" {
	JNIEXPORT void JNICALL Java_com_ohisamallc_ohiapp155_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height);
	JNIEXPORT void JNICALL Java_com_ohisamallc_ohiapp155_GL2JNILib_step(JNIEnv * env, jobject obj);
};
JNIEXPORT void JNICALL Java_com_ohisamallc_ohiapp155_GL2JNILib_init(JNIEnv * env, jobject obj, jint width, jint height) {
	setupGraphics(width, height);
}
JNIEXPORT void JNICALL Java_com_ohisamallc_ohiapp155_GL2JNILib_step(JNIEnv * env, jobject obj) {
	renderFrame();
}


```

# javaソース


```
package com.ohisamallc.ohiapp155;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;

public class MainActivity extends ActionBarActivity {
    GL2JNIView mView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mView = new GL2JNIView(getApplication());
        setContentView(mView);
    }
    @Override protected void onPause() {
        super.onPause();
        mView.onPause();
    }
    @Override protected void onResume() {
        super.onResume();
        mView.onResume();
    }
}

```

# コンパイル手順

```
>set PATH=C:\Users\ore\Downloads\android-ndk-r13b-windows-x86\android-ndk-r13b\build;%PATH%

>cd src/main/jni

>ndk-build

```


以上。