ÈçºÎ°²×°°²×¿µÄ¿ª·¢»·¾³ÒÔ¼°ÔõôÉèÖÃndkµÄ»·¾³±äÁ¿µÈÔÚǰ±ßµÄÎÄÕÂÒѾÓÐÁËÏêϸµÄ½²½â£¬ÔÚÕâÀïÎҾͲ»ÔÙ˵Ã÷£¬Èç¹ûÓв»»á°²×°ºÍÉèÖû·¾³µÄ£¬ÇëÏȲο¼°²×¿»·¾³´î½¨µÄÄÚÈÝ¡£
ºÃ£¬¼ÙÉèÒÔ¼°°²×°ºÃÁËndk£¬Ê¹Óô¿c++¿ª·¢°²×¿³ÌÐò£¬Ï±ßÊÇÏêϸµÄ²½ÖèÓë˵Ã÷£º
1.±àдÈë¿Úº¯Êý
android_mainΪÈë¿Úº¯Êý£¬ºÍC++ÖеÄmainº¯ÊýÊÇÒ»ÑùµÄ¡£ÕâÀï´´½¨CELLAndroidAppµÄ¶ÔÏó£¬Ö±½Óµ÷ÓÃmainº¯Êý¡£
void android_main(struct android_app* state) { CELLAndroidApp app(state); app.main(0,0); } |
˵Ã÷£ºÆäÖÐµÄ CELLAndroidAppÊÇÎÒÃÇÉè¼ÆµÄÒ»¸öͼÐλæÖÆÀ࣬ÉÔºó½«¶ÔÆä×öÏêϸ˵Ã÷
2.»æÖÆÀàµÄʵÏÖ˵Ã÷
2.1ÀàµÄ³ÉԱ˵Ã÷
protected: EGLConfig _config; EGLSurface _surface; EGLContext _context; EGLDisplay _display; android_app* _app; int _width; int _height; |
²¿·Ö²ÎÊý˵Ã÷£º
_surface:ÓÃÓÚ»æÖÆÍ¼ÐΣ¬Ï൱ÓÚwindows»æÍ¼ÖеÄλͼ
_context£º¿ÉÒÔ¿´×öÊÇopengl¶ÔÏó
_display£ºÓÃÓÚ»æÍ¼µÄÉ豸ÉÏÏÂÎÄ£¬ÀàËÆÓÚwindows»æÍ¼ÖеÄdc
2.2 ¹¹Ô캯Êý˵Ã÷
CELLAndroidApp(android_app* app):_app(app) { _surface = 0; _context = 0; _display = 0; _width = 64; _height = 48; app->userData = this; //Óû§Êý¾Ý app->onAppCmd = handle_cmd; //´°¿ÚµÄ´´½¨Ïú»ÙµÈ app->onInputEvent = handle_input; //»Øµ÷º¯Êý } |
ÖµµÃ×¢ÒâµÄÊÇ£¬ÕâÀïµÄappÖеÄuserData£¬´«ÈëÓû§Êý¾Ý£¬ÕâÀïÖ±½Ó´«Èëthis£¬onAppCmd´«ÈëµÄhandle_cmd»Øµ÷º¯Êý£¬onInputEvent´«ÈëµÄÊÂhandle_input»Øµ÷º¯Êý
2.3 ÀàÖк¯Êýmain()˵Ã÷
virtual void main(int argc,char** argv) { int ident; int events; android_poll_source* source; while (true) { while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) { if (source != NULL) source->process(_app, source); //Óд¥Ãþʼþ£¬µ÷ÓÃinputº¯Êý,Ï൱ÓÚdispatchmessage if (_app->destroyRequested != 0) return; } render(); } } |
ÆäÖеÄandroid_poll_sourceÏ൱ÓÚwindowsÖеÄÏûÏ¢¶ÓÁУ¬ÓÃÓÚ´æ·ÅÏûÏ¢£¬Õâ¸öº¯ÊýÖÐÄ£ÄâÁËwindowsÖеÄÏûÏ¢»úÖÆ¡£
ALooper_pollAll()º¯Êý£¬ÓÃÓÚ»ñÈ¡ÏûÏ¢¡£ÖµµÃ×¢ÒâµÄÊǵÚÒ»¸ö²ÎÊý£¬Èç¹ûµÚÒ»¸ö²ÎÊý´«Èë0£¬Ôò²»µÈ´ý£¬µ÷ÓúóÖ±½Ó·µ»Ø£¬ÀàËÆÓÚwindowsÏûÏ¢»úÖÆÖеÄpickMessage()º¯Êý£¬Èç¹û´«Èë-1£¬ÔòÀàËÆÓÚwindowsÏûÏ¢»úÖÆÖеÄSendMessage()º¯Êý¡£
·µ»ØÖµ£ºÈç¹û·µ»ØÖµ´óÓÚ´óÓÚµÈÓÚ0±íʾ»ñÈ¡µ½Êý¾Ý£¬Èç¹ûΪ-1Ôò±íʾʧ°Ü£¬Î´»ñÈ¡µ½Êý¾Ý¡£
ÆäÖз¢sourceÈç¹û²»Îª¿Õ£¬Ôò±íʾÓд¥Ãþʼþ£¬Ôòµ÷ÓÃprocess()º¯Êý£¬Ï൱ÓÚwindowsÖе÷ÓÃdispatchMessage()º¯Êý¡£
×îºó£¬µ÷ÓÃrender()º¯Êý£¬»æÖÆÍ¼ÐΡ£
2.4 ³õʼ»¯É豸º¯ÊýinitDevice()
virtual void initDevice() { const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; EGLint format; EGLint numConfigs; _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(_app->window, 0, 0, format); _surface = eglCreateWindowSurface(_display, _config, _app->window, NULL); #if 0 EGLint contextAtt[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; _context = eglCreateContext(_display, _config, 0, contextAtt); #else _context = eglCreateContext(_display, _config, 0, 0); #endif if (eglMakeCurrent(_display, _surface, _surface, _context) == EGL_FALSE) { LOGW("Unable to eglMakeCurrent"); return; } eglQuerySurface(_display, _surface, EGL_WIDTH, &_width); eglQuerySurface(_display, _surface, EGL_HEIGHT, &_height); onCreate(); // Initialize GL state. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); glDisable(GL_DEPTH_TEST); glViewport(0,0,_width,_height); glOrthof(0,_width,_height,0,-100,100); } |
Ê×ÏÈÐèҪ˵Ã÷µÄÊÇattribsÊý×飬¸ÄÊý×éÖÐÖ÷Òª´æ´¢ÁË»æÖÆÍ¼ÐεÄһЩÊôÐÔÐÅÏ¢£¬ËûÃÇÊdzɶԳöÏֵģ¬ÈçEGL_SURFACE_TYPEÔò±íʾ»æÖÆÍ¼ÐÎÀàÐÍ£¬
EGL_WINDOW_BITÔò±íʾ»æÖƵ½´°¿ÚÉÏ¡£
eglGetDisplay()º¯Êý£º±íʾ»ñȡһ¸öÏÔʾÉ豸
eglInitialize()£º±íʾ³õʼ»¯»ñÈ¡µ½µÄÏÔʾÉ豸
eglChooseConfig()£º»æÖÆÊôÐÔµÄÅäÖÃ
eglGetConfigAttrib()£ºÉèÖûæÖƸñʽ
ANativeWindow_setBuffersGeometry()£º½«¸ñʽӦÓõ½´°¿Ú
eglCreateWindowSurface()£º´´½¨»æÍ¼´°¿Ú
eglCreateContext()£º´´½¨openglµÄ»æÍ¼ÉÏÏÂÎÄ
eglMakeCurrent()£º°ó¶¨µ½»æÍ¼É豸ÉÏÏÂÎÄ
eglQuerySurface()£º»ñȡͼƬµÄ¿í¶ÈºÍ¸ß¶È£¬¾ßÌå»ñÈ¡ÄÄÒ»¸ö¸ù¾Ý×îºóÒ»¸ö²ÎÊýÈ·¶¨
glHint()¡¢glEnable()ºÍglOrthof()µÈº¯ÊýÔòÊÇÓë»æÍ¼µÄͶӰÏà¹ØµÄÄÚÈÝ£¬°üÀ¨³õʼ»¯¡¢ÉèÖÃģʽµÈÄÚÈÝ¡£
2.5 »æÖƺ¯Êýrender()
virtual void render() { if(_display == 0) { return; } glClearColor(0,0,0, 1); glClear(GL_COLOR_BUFFER_BIT); glEnableClientState(GL_VERTEX_ARRAY); if(g_arVertex.size() >= 2) { glColor4f(1,1,1,1); glVertexPointer(3,GL_FLOAT,0,&g_arVertex[0]); glDrawArrays(GL_LINE_STRIP,0,g_arVertex.size()); } eglSwapBuffers(_display,_surface); //Ë«»º´æµÄ½»»»»º³åÇø } |
render()º¯ÊýÖ÷ÒªÓÃÓÚ»æÖƵ㣬¶ÔÖ÷ÒªµÄ¼¸¸öº¯Êý×öÈçÏÂ˵Ã÷£º
glClearColor()£ºÓÃÓÚ½«ÆÁÄ»ÇåΪºÚÉ«
glClear()£ºÇå¿ÕÑÕÉ«»º³åÇø
glEnableClientState()£ºÆô¶¯¶¨µãÊý×é
glVertexPointer()£ºÖƶ¨¶¨µã»º³åÇø
glDrawArrays()£º»æÖƵãÊý×é
eglSwapBuffers()£ºÀàËÆË«»º´æµÄ½»»»»º³åÇø
2.6 handle_cmd()º¯Êý
static void handle_cmd(android_app* app, int32_t cmd) { CELLAndroidApp* pThis = (CELLAndroidApp*)app->userData; pThis->cmd(app,cmd); } |
2.7 handle_input()º¯Êý
static void handle_input(android_app* app, AInputEvent* event) { CELLAndroidApp* pThis = (CELLAndroidApp*)app->userData; pThis->input(app,event); } |
2.8 input()º¯Êý
virtual int input(struct android_app* app, AInputEvent* event) { int32_t evtType = AInputEvent_getType(event); switch(evtType) { case AINPUT_EVENT_TYPE_KEY: break; case AINPUT_EVENT_TYPE_MOTION: { int32_t sourceId = AInputEvent_getSource(event); if(AINPUT_SOURCE_TOUCHSCREEN == sourceId) { int32_t id = AMotionEvent_getAction(event); switch(id) { case AMOTION_EVENT_ACTION_MOVE: { size_t cnt = AMotionEvent_getPointerCount(event); for( int i = 0 ;i < cnt; ++ i ) { float x = AMotionEvent_getX(event,i); float y = AMotionEvent_getY(event,i); float3 pt; pt.x = x; pt.y = y; pt.z = 0; g_arVertex.push_back(pt); } } break; case AMOTION_EVENT_ACTION_DOWN: { size_t cnt = AMotionEvent_getPointerCount(event); for( int i = 0 ;i < cnt; ++ i ) { float x = AMotionEvent_getX(event,i); float y = AMotionEvent_getY(event,i); } } break; case AMOTION_EVENT_ACTION_UP: { size_t cnt = AMotionEvent_getPointerCount(event); for( int i = 0 ;i < cnt; ++ i ) { float x = AMotionEvent_getX(event,i); float y = AMotionEvent_getY(event,i); } } break; } } else if(AINPUT_SOURCE_TRACKBALL == sourceId) { } } break; } return 0; } |
¸Ãº¯ÊýÖ÷ÒªÓÃÓÚ¶ÔÊäÈë½øÐÐÅжϣ¬ÒÔÈ·¶¨ÊǼª¼üÅÌ¡¢Êó±ê»òÒ£¸ÐµÈ£¬¸ù¾Ý¾ßÌåÊäÈë×öÏàÓ¦µÄ²Ù×Ý£¬ÕâÀï¾Í²»ÔÙ×ö¹ý¶àµÄ˵Ã÷
AMotionEvent_getPointerCount()£ºÈç¹ûÊǶàµã´¥¿Ø£¬Ôò½«¸÷¸öµã±£´æµ½vectorÖС£
2.9 cmd()º¯Êý
virtual int cmd(struct android_app* app, int32_t cmd) { switch(cmd) { case APP_CMD_SAVE_STATE: break; case APP_CMD_INIT_WINDOW: initDevice(); break; case APP_CMD_TERM_WINDOW: shutDownDevice(); break; case APP_CMD_GAINED_FOCUS: break; case APP_CMD_LOST_FOCUS: break; } return 0; } |
¸ù¾Ý´«ÈëµÄÃüÁ¶Ô´°¿Ú×öÏàÓ¦µÄ´¦Àí¡£
APP_CMD_INIT_WINDOW£º±íʾ³õʼ»¯´°¿Ú
2.10 shutDownDevice()º¯Êý
virtual void shutDownDevice() { onDestroy(); if (_display != EGL_NO_DISPLAY) { eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (_context != EGL_NO_CONTEXT) { eglDestroyContext(_display, _context); } if (_surface != EGL_NO_SURFACE) { eglDestroySurface(_display, _surface); } eglTerminate(_display); } _display = EGL_NO_DISPLAY; _context = EGL_NO_CONTEXT; _surface = EGL_NO_SURFACE; } |
¹Ø±ÕÉ豸£¬Ö÷ÒªÊǽ«ÓëÉ豸Ïà¹ØµÄ°ó¶¨Çå³ý£¬ÊͷŰ󶨡£
±àдÍêÉϱߵĴúÂëºó£¬±àÒë³ÌÐò£¬½«³ÌÐòµ¼È뵽ģÄâÆ÷ÖУ¬×îÖÕÔËÐеÄЧ¹ûͼÈçÏ£º

|