ホームに戻る
 NDK 立体のアニメ

// 立体が回転します

#include <time.h>
#include <jni.h>
#include <errno.h>

#include <EGL/egl.h>
#include <GLES/gl.h>

#include <android_native_app_glue.h>

#define ONE_SECOND 1000000

struct engine{
  struct android_app* app;

  int32_t count; // アニメのカウント

  int animating;
  EGLDisplay display;
  EGLSurface surface;
  EGLContext context;
  int32_t width;
  int32_t height;
};

// 三角形の座標
GLfloat quadBuf[] ={
  -1.0,  1.0, 0.0,
  -1.0, -1.0, 0.0,
   1.0, -1.0, 0.0,
   1.0,  1.0, 0.0
};

// 法線
GLfloat normBuf[] ={
  0.0, 0.0, 1.0,
  0.0, 0.0, 1.0,
  0.0, 0.0, 1.0,
  0.0, 0.0, 1.0
};

// 光源の設定
GLfloat lightAmb[] = {0.0, 0.0, 0.0, 1.0};
GLfloat lightPos[] = {0.0, 0.0, 0.0, 1.0};
GLfloat lightDif[] = {1.0, 1.0, 1.0, 1.0};

static int engine_init_display(struct engine* engine){
  EGLint attribs[] = {
    EGL_SURFACE_TYPE,
    EGL_WINDOW_BIT,
    EGL_BLUE_SIZE, 8,
    EGL_GREEN_SIZE, 8,
    EGL_RED_SIZE, 8,
    EGL_NONE
  };

  EGLint w, h, format;
  EGLint numConfigs;
  EGLConfig config;
  EGLSurface surface;
  EGLContext context;

  EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

  eglInitialize(display, 0, 0);
  eglChooseConfig(display, attribs, &config, 1, &numConfigs);
  eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);

  ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
  surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
  context = eglCreateContext(display, config, NULL, NULL);

  if(eglMakeCurrent(display, surface, surface, context) == EGL_FALSE){
    return -1;
  }

  eglQuerySurface(display, surface, EGL_WIDTH, &w);
  eglQuerySurface(display, surface, EGL_HEIGHT, &h);

  engine->display = display;
  engine->context = context;
  engine->surface = surface;
  engine->width = w;
  engine->height = h;

  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

  glViewport(0, 0, w, h);

  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();

  glFrustumf(-1.33, 1.33, -1.0, 1.0, 1.0, 5.0);

  glMatrixMode(GL_MODELVIEW);

  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);

  glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
  glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDif);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);

  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_NORMAL_ARRAY);


  return 0;
}

static void engine_draw_frame(struct engine* engine){
  if(engine->display == NULL){
    return;
  }

  glClearColor(0.0, 0.0, 0.0, 1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glLoadIdentity();

  glTranslatef(0.0, 0.0, -3.0);

  glRotatef((float)engine->count, 0.0, 1.0, 0.0);

  glPushMatrix();

  glTranslatef(0.0, 0.0, 1.0);

  glVertexPointer(3, GL_FLOAT, 0, quadBuf);
  glNormalPointer(GL_FLOAT, 0, normBuf);
  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

  glPopMatrix();

  glPushMatrix();

  glTranslatef(0.0, 0.0, -1.0);
  glRotatef(180.0, 0.0, 1.0, 0.0);

  glVertexPointer(3, GL_FLOAT, 0, quadBuf);
  glNormalPointer(GL_FLOAT, 0, normBuf);
  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

  glPopMatrix();

  glPushMatrix();

  glTranslatef(1.0, 0.0, 0.0);
  glRotatef(90.0, 0.0, 1.0, 0.0);

  glVertexPointer(3, GL_FLOAT, 0, quadBuf);
  glNormalPointer(GL_FLOAT, 0, normBuf);
  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

  glPopMatrix();

  glPushMatrix();

  glTranslatef(-1.0, 0.0, 0.0);
  glRotatef(-90.0, 0.0, 1.0, 0.0);

  glVertexPointer(3, GL_FLOAT, 0, quadBuf);
  glNormalPointer(GL_FLOAT, 0, normBuf);
  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

  glPopMatrix();

  eglSwapBuffers(engine->display, engine->surface);
}

static void engine_term_display(struct engine* engine){
  if(engine->display != EGL_NO_DISPLAY){
    eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    if(engine->context != EGL_NO_CONTEXT){
      eglDestroyContext(engine->display, engine->context);
    }
    if(engine->surface != EGL_NO_SURFACE){
      eglDestroySurface(engine->display, engine->surface);
    }
    eglTerminate(engine->display);
  }
  engine->animating = 0;
  engine->display = EGL_NO_DISPLAY;
  engine->context = EGL_NO_CONTEXT;
  engine->surface = EGL_NO_SURFACE;
}

// 入力に対する処理
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
  struct engine* engine = (struct engine*)app->userData;
  if(AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION){
    if(engine->animating){
       engine->animating= 0;
    }
    else{
       engine->animating= 1;
    }
    return 1;
  }
  return 0;
}

// 入力以外のイベントに対する処理
static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
  struct engine* engine = (struct engine*)app->userData;
  switch(cmd){
    case APP_CMD_INIT_WINDOW:
      if(engine->app->window != NULL){
        engine_init_display(engine);
        engine_draw_frame(engine);
        engine->animating = 1;
      }
      break;
    case APP_CMD_TERM_WINDOW:
      engine_term_display(engine);
      break;
    default:
      break;
  }
}

void android_main(struct android_app* state){
  struct engine engine;
  clock_t start, end;

  app_dummy();

  memset(&engine, 0, sizeof(engine));
  state->userData = &engine;
  state->onAppCmd = engine_handle_cmd;
  state->onInputEvent = engine_handle_input;
  engine.app = state;

  start = clock();

  while(1){
    int ident;
    int events;

    struct android_poll_source* source;

    while((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, (void**)&source)) >= 0){
      if(source != NULL){
        source->process(state, source);
      }

      if(state->destroyRequested != 0){
        engine_term_display(&engine);
        return;
      }
    }

    if(engine.animating){
      end = clock();

      if(end - start > (ONE_SECOND / 100)){
        start = clock();
        engine.count++;
        engine_draw_frame(&engine);
      }
    }
  }
}


inserted by FC2 system