找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3650|回复: 0

【安卓】NDK+OpenGL的一个简单的例子

[复制链接]
发表于 2014-8-18 18:43:28 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
我讨厌Eclipse.各种麻烦,配置还需要下载各种包,各种不爽!
也许是我用不来,也许是我笨。总之在我的电脑上它从来没正常运行过。
好吧。那我就用c4droid进行开发。先在电脑上用Notepad++写代码,完了以后仍手机用c4droid变异。
首先我们需要一个Makefile
  1. all: ndkapp.so

  2. ndkapp.so: napp.o
  3.     $(CC) -o ndkapp.so napp.o -shared -lEGL -lGLESv1_CM -lm

  4. clean:
  5.     rm ndkapp.so napp.o
复制代码
我们是把napp.c这个源文件编译为napp.o,然后链接得到ndkapp.so这个可执行文件(安卓的可执行文件……?)
算了,不纠结这个。继续。
这个源码运行的效果就是屏幕上会显示一个正方形,然后你用手摸屏幕的时候正方形会跟着走。
我决定以后在安卓上开发程序都采取用OpenGL自己绘制界面的这种方式了。我更喜欢这种模式的编程。
  1. #include<jni.h>
  2. #include<errno.h>
  3. #include<math.h>

  4. #include<sys/time.h>

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

  7. #include<android/sensor.h>
  8. #include<android/log.h>
  9. #include<android_native_app_glue.h>

  10. #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,"native-activity",__VA_ARGS__))
  11. #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN,"native-activity",__VA_ARGS__))

  12. //程序挂起恢复时存储的数据
  13. typedef struct
  14. {
  15.     int32_t x;
  16.     int32_t y;
  17.    
  18.     float   AccX,AccY,AccZ;
  19. }SavedState,*SavedStateP;

  20. //程序数据
  21. typedef struct
  22. {
  23.     struct android_app      *pApp;

  24.     //传感器
  25.     ASensorManager          *pSensorManager;
  26.     const ASensor           *pAccelerometerSensor;
  27.     ASensorEventQueue       *pSensorEventQueue;
  28.    
  29.     //图形引擎
  30.     EGLDisplay              Display;
  31.     EGLSurface              Surface;
  32.     EGLContext              Context;
  33.     int32_t                 Width;
  34.     int32_t                 Height;
  35.    
  36.     //存储的状态
  37.     SavedState              State;
  38. }AppData,*AppDataP;

  39. //=============================================================================
  40. //InitDisplay:
  41. //初始化显示的部分,OpenGL ES
  42. //-----------------------------------------------------------------------------
  43. int InitDisplay(AppDataP pThis)
  44. {
  45.     const EGLint Attribs[]=
  46.     {
  47.         EGL_SURFACE_TYPE,EGL_WINDOW_BIT,
  48.         EGL_BLUE_SIZE,8,
  49.         EGL_GREEN_SIZE,8,
  50.         EGL_RED_SIZE,8,
  51.         EGL_DEPTH_SIZE,8,
  52.         EGL_NONE
  53.     };
  54.     EGLint      W,H;
  55.     EGLint      Dummy,Format;
  56.     EGLint      NbConfigs;
  57.     EGLConfig   Configs;
  58.     EGLDisplay  Display;
  59.     EGLSurface  Surface;
  60.     EGLContext  Context;
  61.    
  62.     Display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
  63.     eglInitialize(Display,0,0);
  64.     eglChooseConfig(Display,Attribs,&Configs,1,&NbConfigs);
  65.     eglGetConfigAttrib(Display,Configs,EGL_NATIVE_VISUAL_ID,&Format);
  66.     ANativeWindow_setBuffersGeometry(pThis->pApp->window,0,0,Format);
  67.     Surface=eglCreateWindowSurface(Display,Configs,pThis->pApp->window,NULL);
  68.     Context=eglCreateContext(Display,Configs,NULL,NULL);
  69.     if(eglMakeCurrent(Display,Surface,Surface,Context)==EGL_FALSE)
  70.     {
  71.         LOGW("Unable to eglMakeCurrent");
  72.         return 0;
  73.     }
  74.     eglQuerySurface(Display,Surface,EGL_WIDTH,&W);
  75.     eglQuerySurface(Display,Surface,EGL_HEIGHT,&H);
  76.    
  77.     pThis->Display=Display;
  78.     pThis->Context=Context;
  79.     pThis->Surface=Surface;
  80.     pThis->Width=W;
  81.     pThis->Height=H;
  82.    
  83.     glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_FASTEST);
  84.     glEnable(GL_DEPTH_TEST);
  85.     glDepthFunc(GL_LEQUAL);

  86.     glClearColor(0.0f,0.0f,0.0f,0.0f);
  87.     glClearDepthf(1.0f);
  88.     glShadeModel(GL_FLAT);
  89.    
  90.     glViewport(0,0,W,H);
  91.    
  92.     glMatrixMode(GL_PROJECTION);
  93.     glLoadIdentity();
  94.    
  95.     glMatrixMode(GL_MODELVIEW);
  96.     glLoadIdentity();

  97.     return 1;
  98. }

  99. //=============================================================================
  100. //CleanupDisplay:
  101. //清理显示的部分,释放内存。和InitDisplay配套的
  102. //-----------------------------------------------------------------------------
  103. void CleanupDisplay(AppDataP pThis)
  104. {
  105.     if(pThis->Display!=EGL_NO_DISPLAY)
  106.     {
  107.         eglMakeCurrent(pThis->Display,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
  108.         if(pThis->Context!=EGL_NO_CONTEXT)
  109.             eglDestroyContext(pThis->Display,pThis->Context);
  110.         if(pThis->Surface!=EGL_NO_SURFACE)
  111.             eglDestroySurface(pThis->Display,pThis->Surface);
  112.         eglTerminate(pThis->Display);
  113.     }
  114.     pThis->Display=EGL_NO_DISPLAY;
  115.     pThis->Context=EGL_NO_CONTEXT;
  116.     pThis->Surface=EGL_NO_SURFACE;
  117. }

  118. GLfloat Model[3*6]=//模型
  119. {
  120.     -0.1,-0.1,0.5,//两个三角形组成一个四边形
  121.      0.1,-0.1,0.5,
  122.     -0.1, 0.1,0.5,
  123.      0.1,-0.1,0.5,
  124.      0.1, 0.1,0.5,
  125.     -0.1, 0.1,0.5
  126. };

  127. //圆周率之类的东西
  128. #define PI 3.141592653589793238462643

  129. //=============================================================================
  130. //DrawFrame:
  131. //在屏幕上画一帧图像
  132. //-----------------------------------------------------------------------------
  133. void DrawFrame(AppDataP pThis)
  134. {
  135.     GLfloat Aspect;
  136.     double  CurTime;
  137.     struct  timeval tv;
  138.     GLfloat Matrix[4*4];

  139.     if(!pThis->Display)
  140.         return;
  141.         
  142.     gettimeofday(&tv,NULL);//取得时间
  143.     CurTime=tv.tv_sec+tv.tv_usec*0.000001;//以秒为单位的时间

  144.     Aspect=(GLfloat)(pThis->Height)/(GLfloat)(pThis->Width);//宽高比
  145.         
  146.     //清空图形缓冲区
  147.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  148.    
  149.     //加载模型
  150.     glVertexPointer(3,GL_FLOAT,0,Model);
  151.     glEnableClientState(GL_VERTEX_ARRAY);
  152.    
  153.     //设置矩阵
  154.     glLoadIdentity();//载入单位矩阵
  155.    
  156.     memset(&Matrix,0,sizeof(Matrix));
  157.     Matrix[10]=Matrix[15]=1;
  158.    
  159.     //绕Z轴旋转
  160.     Matrix[0]=(GLfloat)sin(CurTime);
  161.     Matrix[1]=(GLfloat)cos(CurTime);
  162.     Matrix[4]=-Matrix[1];
  163.     Matrix[5]=Matrix[0];
  164.    
  165.     //宽高比缩放
  166.     Matrix[0]*=Aspect;
  167.     Matrix[4]*=Aspect;
  168.    
  169.     //位移
  170.     Matrix[12]=((GLfloat)(pThis->State.x)/(GLfloat)(pThis->Width))*2-1;
  171.     Matrix[13]=1-((GLfloat)(pThis->State.y)/(GLfloat)(pThis->Height))*2;
  172.     glMultMatrixf(Matrix);
  173.    
  174.     glColor4f(0,1,0,1);//绿色
  175.     glDrawArrays(GL_TRIANGLES,0,6);//画模型
  176.    
  177.     glFlush();
  178.     eglSwapBuffers(pThis->Display,pThis->Surface);//把缓冲区的图像刷到屏幕上
  179. }

  180. //=============================================================================
  181. //CmdProc:
  182. //处理窗口消息
  183. //-----------------------------------------------------------------------------
  184. static void CmdProc(struct android_app*pApp,int32_t cmd)
  185. {
  186. #   define  pThis   ((AppDataP)pApp->userData)

  187.     switch(cmd)
  188.     {
  189.     case APP_CMD_SAVE_STATE://保存状态
  190.         pThis->pApp->savedState=malloc(sizeof(SavedState));
  191.         if(pThis->pApp->savedState)
  192.         {
  193.             memcpy(pThis->pApp->savedState,&(pThis->State),sizeof(SavedState));
  194.             pThis->pApp->savedStateSize=sizeof(SavedState);
  195.         }
  196.         break;
  197.     case APP_CMD_INIT_WINDOW://初始化窗口
  198.         if(pThis->pApp->window)
  199.         {
  200.             InitDisplay(pThis);
  201.             DrawFrame(pThis);
  202.         }
  203.         break;
  204.     case APP_CMD_TERM_WINDOW://结束窗口
  205.         CleanupDisplay(pThis);
  206.         break;
  207.     case APP_CMD_GAINED_FOCUS://取得焦点
  208.         if(pThis->pAccelerometerSensor)
  209.         {
  210.             ASensorEventQueue_enableSensor(pThis->pSensorEventQueue,pThis->pAccelerometerSensor);
  211.             ASensorEventQueue_setEventRate(pThis->pSensorEventQueue,pThis->pAccelerometerSensor,50000);
  212.         }
  213.         break;
  214.     case APP_CMD_LOST_FOCUS://失去焦点
  215.         if (pThis->pAccelerometerSensor)
  216.             ASensorEventQueue_disableSensor(pThis->pSensorEventQueue,pThis->pAccelerometerSensor);
  217.         break;
  218.     }

  219. #   undef   pThis
  220. }

  221. //=============================================================================
  222. //InputProc:
  223. //处理触摸操作
  224. //-----------------------------------------------------------------------------
  225. static int32_t InputProc(struct android_app*pApp,AInputEvent*pEvent)
  226. {
  227. #   define  pThis   ((AppDataP)pApp->userData)
  228.     if(AInputEvent_getType(pEvent)==AINPUT_EVENT_TYPE_MOTION)
  229.     {
  230.         pThis->State.x=AMotionEvent_getX(pEvent,0);
  231.         pThis->State.y=AMotionEvent_getY(pEvent,0);
  232.         return 1;
  233.     }
  234.     return 0;
  235. #   undef   pThis
  236. }

  237. //=============================================================================
  238. //android_main:
  239. //程序入口点
  240. //-----------------------------------------------------------------------------
  241. void android_main(struct android_app*pApp)
  242. {
  243.     AppData This;

  244.     // Make sure glue isn't stripped.
  245.     app_dummy();

  246.     memset(&This,0,sizeof(This));
  247.     pApp->userData=&This;
  248.     pApp->onAppCmd=CmdProc;
  249.     pApp->onInputEvent=InputProc;
  250.     This.pApp=pApp;

  251.     //初始化传感器
  252.     This.pSensorManager=ASensorManager_getInstance();
  253.     This.pAccelerometerSensor=ASensorManager_getDefaultSensor(This.pSensorManager,ASENSOR_TYPE_ACCELEROMETER);
  254.     This.pSensorEventQueue=ASensorManager_createEventQueue(This.pSensorManager,pApp->looper,LOOPER_ID_USER,NULL,NULL);

  255.     if(pApp->savedState)//从已有的状态恢复回来
  256.         memcpy(&(This.State),pApp->savedState,sizeof(SavedState));

  257.     for(;;)
  258.     {
  259.         int iIdent;
  260.         int iEvents;
  261.         struct android_poll_source*pSource;
  262.         
  263.         //从传感器读取事件
  264.         while((iIdent=ALooper_pollAll(0,NULL,&iEvents,(void**)&pSource))>=0)
  265.         {
  266.             //处理事件
  267.             if(pSource)
  268.                 pSource->process(pApp,pSource);

  269.             //如果传感器有数据,处理它
  270.             if(iIdent==LOOPER_ID_USER)
  271.             {
  272.                 if(This.pAccelerometerSensor)
  273.                 {
  274.                     ASensorEvent sEvent;
  275.                     while(ASensorEventQueue_getEvents(This.pSensorEventQueue,&sEvent,1)>0)//取得加速度传感器的采样
  276.                     {
  277.                         This.State.AccX=sEvent.acceleration.x;
  278.                         This.State.AccY=sEvent.acceleration.y;
  279.                         This.State.AccZ=sEvent.acceleration.z;
  280.                     }
  281.                 }
  282.             }
  283.             if(pApp->destroyRequested)//退出消息
  284.             {
  285.                 CleanupDisplay(&This);
  286.                 return;
  287.             }
  288.         }
  289.         DrawFrame(&This);//更新显示
  290.     }
  291. }
复制代码
回复

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-23 19:54 , Processed in 0.039812 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表