【安卓】NDK+OpenGL的一个简单的例子
我讨厌Eclipse.各种麻烦,配置还需要下载各种包,各种不爽!也许是我用不来,也许是我笨。总之在我的电脑上它从来没正常运行过。
好吧。那我就用c4droid进行开发。先在电脑上用Notepad++写代码,完了以后仍手机用c4droid变异。
首先我们需要一个Makefileall: ndkapp.so
ndkapp.so: napp.o
$(CC) -o ndkapp.so napp.o -shared -lEGL -lGLESv1_CM -lm
clean:
rm ndkapp.so napp.o我们是把napp.c这个源文件编译为napp.o,然后链接得到ndkapp.so这个可执行文件(安卓的可执行文件……?)
算了,不纠结这个。继续。
这个源码运行的效果就是屏幕上会显示一个正方形,然后你用手摸屏幕的时候正方形会跟着走。
我决定以后在安卓上开发程序都采取用OpenGL自己绘制界面的这种方式了。我更喜欢这种模式的编程。#include<jni.h>
#include<errno.h>
#include<math.h>
#include<sys/time.h>
#include<EGL/egl.h>
#include<GLES/gl.h>
#include<android/sensor.h>
#include<android/log.h>
#include<android_native_app_glue.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,"native-activity",__VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN,"native-activity",__VA_ARGS__))
//程序挂起恢复时存储的数据
typedef struct
{
int32_t x;
int32_t y;
float AccX,AccY,AccZ;
}SavedState,*SavedStateP;
//程序数据
typedef struct
{
struct android_app *pApp;
//传感器
ASensorManager *pSensorManager;
const ASensor *pAccelerometerSensor;
ASensorEventQueue *pSensorEventQueue;
//图形引擎
EGLDisplay Display;
EGLSurface Surface;
EGLContext Context;
int32_t Width;
int32_t Height;
//存储的状态
SavedState State;
}AppData,*AppDataP;
//=============================================================================
//InitDisplay:
//初始化显示的部分,OpenGL ES
//-----------------------------------------------------------------------------
int InitDisplay(AppDataP pThis)
{
const EGLint Attribs[]=
{
EGL_SURFACE_TYPE,EGL_WINDOW_BIT,
EGL_BLUE_SIZE,8,
EGL_GREEN_SIZE,8,
EGL_RED_SIZE,8,
EGL_DEPTH_SIZE,8,
EGL_NONE
};
EGLint W,H;
EGLint Dummy,Format;
EGLint NbConfigs;
EGLConfig Configs;
EGLDisplayDisplay;
EGLSurfaceSurface;
EGLContextContext;
Display=eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(Display,0,0);
eglChooseConfig(Display,Attribs,&Configs,1,&NbConfigs);
eglGetConfigAttrib(Display,Configs,EGL_NATIVE_VISUAL_ID,&Format);
ANativeWindow_setBuffersGeometry(pThis->pApp->window,0,0,Format);
Surface=eglCreateWindowSurface(Display,Configs,pThis->pApp->window,NULL);
Context=eglCreateContext(Display,Configs,NULL,NULL);
if(eglMakeCurrent(Display,Surface,Surface,Context)==EGL_FALSE)
{
LOGW("Unable to eglMakeCurrent");
return 0;
}
eglQuerySurface(Display,Surface,EGL_WIDTH,&W);
eglQuerySurface(Display,Surface,EGL_HEIGHT,&H);
pThis->Display=Display;
pThis->Context=Context;
pThis->Surface=Surface;
pThis->Width=W;
pThis->Height=H;
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_FASTEST);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClearDepthf(1.0f);
glShadeModel(GL_FLAT);
glViewport(0,0,W,H);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return 1;
}
//=============================================================================
//CleanupDisplay:
//清理显示的部分,释放内存。和InitDisplay配套的
//-----------------------------------------------------------------------------
void CleanupDisplay(AppDataP pThis)
{
if(pThis->Display!=EGL_NO_DISPLAY)
{
eglMakeCurrent(pThis->Display,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
if(pThis->Context!=EGL_NO_CONTEXT)
eglDestroyContext(pThis->Display,pThis->Context);
if(pThis->Surface!=EGL_NO_SURFACE)
eglDestroySurface(pThis->Display,pThis->Surface);
eglTerminate(pThis->Display);
}
pThis->Display=EGL_NO_DISPLAY;
pThis->Context=EGL_NO_CONTEXT;
pThis->Surface=EGL_NO_SURFACE;
}
GLfloat Model=//模型
{
-0.1,-0.1,0.5,//两个三角形组成一个四边形
0.1,-0.1,0.5,
-0.1, 0.1,0.5,
0.1,-0.1,0.5,
0.1, 0.1,0.5,
-0.1, 0.1,0.5
};
//圆周率之类的东西
#define PI 3.141592653589793238462643
//=============================================================================
//DrawFrame:
//在屏幕上画一帧图像
//-----------------------------------------------------------------------------
void DrawFrame(AppDataP pThis)
{
GLfloat Aspect;
doubleCurTime;
structtimeval tv;
GLfloat Matrix;
if(!pThis->Display)
return;
gettimeofday(&tv,NULL);//取得时间
CurTime=tv.tv_sec+tv.tv_usec*0.000001;//以秒为单位的时间
Aspect=(GLfloat)(pThis->Height)/(GLfloat)(pThis->Width);//宽高比
//清空图形缓冲区
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//加载模型
glVertexPointer(3,GL_FLOAT,0,Model);
glEnableClientState(GL_VERTEX_ARRAY);
//设置矩阵
glLoadIdentity();//载入单位矩阵
memset(&Matrix,0,sizeof(Matrix));
Matrix=Matrix=1;
//绕Z轴旋转
Matrix=(GLfloat)sin(CurTime);
Matrix=(GLfloat)cos(CurTime);
Matrix=-Matrix;
Matrix=Matrix;
//宽高比缩放
Matrix*=Aspect;
Matrix*=Aspect;
//位移
Matrix=((GLfloat)(pThis->State.x)/(GLfloat)(pThis->Width))*2-1;
Matrix=1-((GLfloat)(pThis->State.y)/(GLfloat)(pThis->Height))*2;
glMultMatrixf(Matrix);
glColor4f(0,1,0,1);//绿色
glDrawArrays(GL_TRIANGLES,0,6);//画模型
glFlush();
eglSwapBuffers(pThis->Display,pThis->Surface);//把缓冲区的图像刷到屏幕上
}
//=============================================================================
//CmdProc:
//处理窗口消息
//-----------------------------------------------------------------------------
static void CmdProc(struct android_app*pApp,int32_t cmd)
{
# definepThis ((AppDataP)pApp->userData)
switch(cmd)
{
case APP_CMD_SAVE_STATE://保存状态
pThis->pApp->savedState=malloc(sizeof(SavedState));
if(pThis->pApp->savedState)
{
memcpy(pThis->pApp->savedState,&(pThis->State),sizeof(SavedState));
pThis->pApp->savedStateSize=sizeof(SavedState);
}
break;
case APP_CMD_INIT_WINDOW://初始化窗口
if(pThis->pApp->window)
{
InitDisplay(pThis);
DrawFrame(pThis);
}
break;
case APP_CMD_TERM_WINDOW://结束窗口
CleanupDisplay(pThis);
break;
case APP_CMD_GAINED_FOCUS://取得焦点
if(pThis->pAccelerometerSensor)
{
ASensorEventQueue_enableSensor(pThis->pSensorEventQueue,pThis->pAccelerometerSensor);
ASensorEventQueue_setEventRate(pThis->pSensorEventQueue,pThis->pAccelerometerSensor,50000);
}
break;
case APP_CMD_LOST_FOCUS://失去焦点
if (pThis->pAccelerometerSensor)
ASensorEventQueue_disableSensor(pThis->pSensorEventQueue,pThis->pAccelerometerSensor);
break;
}
# undef pThis
}
//=============================================================================
//InputProc:
//处理触摸操作
//-----------------------------------------------------------------------------
static int32_t InputProc(struct android_app*pApp,AInputEvent*pEvent)
{
# definepThis ((AppDataP)pApp->userData)
if(AInputEvent_getType(pEvent)==AINPUT_EVENT_TYPE_MOTION)
{
pThis->State.x=AMotionEvent_getX(pEvent,0);
pThis->State.y=AMotionEvent_getY(pEvent,0);
return 1;
}
return 0;
# undef pThis
}
//=============================================================================
//android_main:
//程序入口点
//-----------------------------------------------------------------------------
void android_main(struct android_app*pApp)
{
AppData This;
// Make sure glue isn't stripped.
app_dummy();
memset(&This,0,sizeof(This));
pApp->userData=&This;
pApp->onAppCmd=CmdProc;
pApp->onInputEvent=InputProc;
This.pApp=pApp;
//初始化传感器
This.pSensorManager=ASensorManager_getInstance();
This.pAccelerometerSensor=ASensorManager_getDefaultSensor(This.pSensorManager,ASENSOR_TYPE_ACCELEROMETER);
This.pSensorEventQueue=ASensorManager_createEventQueue(This.pSensorManager,pApp->looper,LOOPER_ID_USER,NULL,NULL);
if(pApp->savedState)//从已有的状态恢复回来
memcpy(&(This.State),pApp->savedState,sizeof(SavedState));
for(;;)
{
int iIdent;
int iEvents;
struct android_poll_source*pSource;
//从传感器读取事件
while((iIdent=ALooper_pollAll(0,NULL,&iEvents,(void**)&pSource))>=0)
{
//处理事件
if(pSource)
pSource->process(pApp,pSource);
//如果传感器有数据,处理它
if(iIdent==LOOPER_ID_USER)
{
if(This.pAccelerometerSensor)
{
ASensorEvent sEvent;
while(ASensorEventQueue_getEvents(This.pSensorEventQueue,&sEvent,1)>0)//取得加速度传感器的采样
{
This.State.AccX=sEvent.acceleration.x;
This.State.AccY=sEvent.acceleration.y;
This.State.AccZ=sEvent.acceleration.z;
}
}
}
if(pApp->destroyRequested)//退出消息
{
CleanupDisplay(&This);
return;
}
}
DrawFrame(&This);//更新显示
}
}
页:
[1]