概要
vistaでandroid studio 1.1.0やってみた。
jniやってみた。
練習問題やってみた。
練習問題
jniでopenglでコンパイル済みライブラリーを使え。
方針
- ライブラリーは、assimp使う。
- ndk-build使う。
写真
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
以上。