3dphotoshoot

view src/android/amain.c @ 24:2712c5da2e00

getting sensor input (hack)
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 16 Jun 2015 06:17:59 +0300
parents a94af102872f
children ac80210d5fbe
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <EGL/egl.h>
5 #include <jni.h>
6 #include "amain.h"
7 #include "native_glue.h"
8 #include <android/sensor.h>
9 #include "sensordef.h"
10 #include "logger.h"
11 #include "game.h"
12 #include "camera.h"
13 #include "timer.h"
15 #define EVID_SENS_ACCEL (LOOPER_ID_USER + 0)
16 #define EVID_SENS_ROT (LOOPER_ID_USER + 1)
18 static void handle_command(struct android_app *app, int32_t cmd);
19 static int handle_input(struct android_app *app, AInputEvent *ev);
20 static int handle_touch_input(struct android_app *app, AInputEvent *ev);
21 static int init_gl(void);
22 static void destroy_gl(void);
24 static EGLDisplay dpy;
25 static EGLSurface surf;
26 static EGLContext ctx;
28 static int redisp_pending = 1; /* TODO stop busy-looping */
30 static int width, height;
31 static int init_done;
33 static JavaVM *jvm;
34 static JNIEnv *jni;
35 static jclass activity_class;
37 static ASensorManager *sensorman;
38 static ASensor const *sens_accel;
39 static ASensor const *sens_rot;
40 static ASensorEventQueue *sens_evq_accel;
41 static ASensorEventQueue *sens_evq_rot;
43 void android_main(struct android_app *app_ptr)
44 {
45 app_dummy();
46 app = app_ptr;
48 app->onAppCmd = handle_command;
49 app->onInputEvent = handle_input;
51 start_logger();
53 jvm = app->activity->vm;
54 if((*jvm)->AttachCurrentThread(jvm, &jni, 0) != 0) {
55 fprintf(stderr, "failed to attach native thread to Java VM\n");
56 exit(1);
57 }
58 activity_class = (*jni)->GetObjectClass(jni, app->activity->clazz);
60 {
61 int i, num_sensors;
62 ASensorList sensors;
64 sensorman = ASensorManager_getInstance();
65 num_sensors = ASensorManager_getSensorList(sensorman, &sensors);
66 printf("found %d sensors:\n", num_sensors);
68 for(i=0; i<num_sensors; i++) {
69 ASensor const *sens = sensors[i];
70 int type = ASensor_getType(sens);
71 float res = ASensor_getResolution(sens);
72 int mindel = ASensor_getMinDelay(sens);
74 printf(" %d) [%d:%s] %s - %s (res: %g, min-delay: %d)\n", i,
75 type, sensor_typestr(type), ASensor_getName(sens),
76 ASensor_getVendor(sens), res, mindel);
77 }
79 // try to get a linear acceleration sensor
80 printf("Requesting \"linear acceleration\" sensor ...\n");
81 if(!(sens_accel = ASensorManager_getDefaultSensor(sensorman, SENSOR_TYPE_LINEAR_ACCELERATION))) {
82 fprintf(stderr, "No linear acceleration sensor found, aborting!\n");
83 return;
84 }
86 // try to get a game rotation vector sensor
87 printf("Requesting \"game rotation vector\" sensor ...\n");
88 if(!(sens_rot = ASensorManager_getDefaultSensor(sensorman, SENSOR_TYPE_GAME_ROTATION_VECTOR))) {
89 printf("Requesting \"rotation vector\" sensor ...\n");
90 if(!(sens_rot = ASensorManager_getDefaultSensor(sensorman, SENSOR_TYPE_ROTATION_VECTOR))) {
91 fprintf(stderr, "No rotation sensor found, aborting!\n");
92 return;
93 }
94 }
96 if(!(sens_evq_accel = ASensorManager_createEventQueue(sensorman, app->looper,
97 EVID_SENS_ACCEL, 0, 0))) {
98 fprintf(stderr, "failed to create acceleration sensor event queue\n");
99 return;
100 }
102 if(!(sens_evq_rot = ASensorManager_createEventQueue(sensorman, app->looper,
103 EVID_SENS_ROT, 0, 0))) {
104 fprintf(stderr, "failed to create rotation sensor event queue\n");
105 return;
106 }
107 }
110 for(;;) {
111 int num_events, evid;
112 struct android_poll_source *pollsrc;
113 ASensorEvent sens_ev;
115 while((evid = ALooper_pollAll(redisp_pending ? 0 : -1, 0, &num_events, (void**)&pollsrc)) >= 0) {
117 switch(evid) {
118 case EVID_SENS_ACCEL:
119 if(sens_accel) {
120 float accel[3];
121 while(ASensorEventQueue_getEvents(sens_evq_accel, &sens_ev, 1) > 0) {
122 accel[0] = sens_ev.acceleration.x;
123 accel[1] = sens_ev.acceleration.y;
124 accel[2] = sens_ev.acceleration.z;
125 }
127 // TODO: integrate over time
128 game_6dof_translation(accel[0], accel[1], accel[2]);
129 }
130 break;
132 case EVID_SENS_ROT:
133 if(sens_rot) {
134 float qrot[4];
135 while(ASensorEventQueue_getEvents(sens_evq_rot, &sens_ev, 1) > 0) {
136 int i;
137 for(i=0; i<4; i++) {
138 qrot[i] = sens_ev.data[i];
139 }
140 }
142 game_6dof_rotation(qrot[0], qrot[1], qrot[2], qrot[3]);
143 }
144 break;
146 default:
147 if(pollsrc) {
148 pollsrc->process(app, pollsrc);
149 }
150 }
151 }
153 if(app->destroyRequested) {
154 (*jvm)->DetachCurrentThread(jvm);
155 return;
156 }
158 if(init_done && redisp_pending) {
159 game_display(get_time_msec());
160 eglSwapBuffers(dpy, surf);
161 }
162 }
163 }
165 void set_mouse_pos(int x, int y)
166 {
167 }
169 void set_mouse_cursor(int enable)
170 {
171 }
173 static void handle_command(struct android_app *app, int32_t cmd)
174 {
175 struct cam_android_platform_data cam_data;
177 switch(cmd) {
178 case APP_CMD_SAVE_STATE:
179 /* save the application state to be reloaded on restart if needed */
180 break;
182 case APP_CMD_INIT_WINDOW:
183 if(init_gl() == -1) {
184 exit(1);
185 }
187 cam_data.vm = jvm;
188 cam_data.jni = jni;
189 cam_data.activity_class = activity_class;
191 if(cam_init(&cam_data) == -1) {
192 exit(1);
193 }
195 /* initialize the application */
196 if(game_init() == -1) {
197 exit(1); /* initialization failed, quit */
198 }
199 init_done = 1;
200 break;
202 case APP_CMD_TERM_WINDOW:
203 /* cleanup */
204 init_done = 0;
205 game_shutdown();
206 destroy_gl();
207 break;
209 case APP_CMD_GAINED_FOCUS:
210 /* app focused */
211 printf("Command: APP_CMD_GAINED_FOCUS\n");
212 if(sens_accel) {
213 ASensorEventQueue_enableSensor(sens_evq_accel, sens_accel);
214 ASensorEventQueue_setEventRate(sens_evq_accel, sens_accel, 1000000 / 60);
215 }
216 if(sens_rot) {
217 ASensorEventQueue_enableSensor(sens_evq_rot, sens_rot);
218 ASensorEventQueue_setEventRate(sens_evq_rot, sens_rot, 1000000 / 60);
219 }
220 //cam_start_video();
221 break;
223 case APP_CMD_LOST_FOCUS:
224 /* app lost focus */
225 printf("Command: APP_CMD_LOST_FOCUS\n");
226 if(sens_accel) {
227 ASensorEventQueue_disableSensor(sens_evq_accel, sens_accel);
228 }
229 if(sens_rot) {
230 ASensorEventQueue_disableSensor(sens_evq_rot, sens_rot);
231 }
232 //cam_stop_video();
233 break;
235 case APP_CMD_WINDOW_RESIZED:
236 case APP_CMD_CONFIG_CHANGED:
237 {
238 int nx = ANativeWindow_getWidth(app->window);
239 int ny = ANativeWindow_getHeight(app->window);
240 if(nx != width || ny != height) {
241 game_reshape(nx, ny);
242 width = nx;
243 height = ny;
244 }
245 }
246 break;
248 default:
249 break;
250 }
251 }
253 static int handle_input(struct android_app *app, AInputEvent *ev)
254 {
255 int evtype = AInputEvent_getType(ev);
257 switch(evtype) {
258 case AINPUT_EVENT_TYPE_MOTION:
259 return handle_touch_input(app, ev);
261 default:
262 break;
263 }
264 return 0;
265 }
267 #define MAX_TOUCH_IDS 32
269 static int handle_touch_input(struct android_app *app, AInputEvent *ev)
270 {
271 int x, y, idx, touch_id;
272 unsigned int action;
273 static int prev_pos[MAX_TOUCH_IDS][2];
275 action = AMotionEvent_getAction(ev);
277 idx = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
278 AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
279 touch_id = AMotionEvent_getPointerId(ev, idx);
281 x = AMotionEvent_getX(ev, idx);
282 y = AMotionEvent_getY(ev, idx);
284 switch(action & AMOTION_EVENT_ACTION_MASK) {
285 case AMOTION_EVENT_ACTION_DOWN:
286 case AMOTION_EVENT_ACTION_POINTER_DOWN:
287 game_mouse_button(touch_id, 0, 1, x, y);
288 if(touch_id < MAX_TOUCH_IDS) {
289 prev_pos[touch_id][0] = x;
290 prev_pos[touch_id][1] = y;
291 }
292 break;
294 case AMOTION_EVENT_ACTION_UP:
295 case AMOTION_EVENT_ACTION_POINTER_UP:
296 game_mouse_button(touch_id, 0, 0, x, y);
297 if(touch_id < MAX_TOUCH_IDS) {
298 prev_pos[touch_id][0] = x;
299 prev_pos[touch_id][1] = y;
300 }
301 break;
303 case AMOTION_EVENT_ACTION_MOVE:
304 {
305 int i, pcount = AMotionEvent_getPointerCount(ev);
306 for(i=0; i<pcount; i++) {
307 int id = AMotionEvent_getPointerId(ev, i);
308 if(id < MAX_TOUCH_IDS && x != prev_pos[id][0] && y != prev_pos[id][1]) {
309 game_mouse_motion(id, x, y);
310 prev_pos[id][0] = x;
311 prev_pos[id][1] = y;
312 }
313 }
314 }
315 break;
317 default:
318 break;
319 }
321 return 1;
322 }
325 static int init_gl(void)
326 {
327 static const int eglattr[] = {
328 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
329 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
330 EGL_RED_SIZE, 5,
331 EGL_GREEN_SIZE, 5,
332 EGL_BLUE_SIZE, 5,
333 EGL_DEPTH_SIZE, 16,
334 EGL_NONE
335 };
336 static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
338 EGLConfig eglcfg;
339 int count, vis;
341 dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
342 if(!dpy || !eglInitialize(dpy, 0, 0)) {
343 fprintf(stderr, "failed to initialize EGL\n");
344 destroy_gl();
345 return -1;
346 }
348 if(!eglChooseConfig(dpy, eglattr, &eglcfg, 1, &count)) {
349 fprintf(stderr, "no matching EGL config found\n");
350 destroy_gl();
351 return -1;
352 }
354 /* configure the native window visual according to the chosen EGL config */
355 eglGetConfigAttrib(dpy, &eglcfg, EGL_NATIVE_VISUAL_ID, &vis);
356 ANativeWindow_setBuffersGeometry(app->window, 0, 0, vis);
358 if(!(surf = eglCreateWindowSurface(dpy, eglcfg, app->window, 0))) {
359 fprintf(stderr, "failed to create window\n");
360 destroy_gl();
361 return -1;
362 }
364 if(!(ctx = eglCreateContext(dpy, eglcfg, EGL_NO_CONTEXT, ctxattr))) {
365 fprintf(stderr, "failed to create OpenGL ES context\n");
366 destroy_gl();
367 return -1;
368 }
369 eglMakeCurrent(dpy, surf, surf, ctx);
371 eglQuerySurface(dpy, surf, EGL_WIDTH, &width);
372 eglQuerySurface(dpy, surf, EGL_HEIGHT, &height);
373 game_reshape(width, height);
375 return 0;
376 }
378 static void destroy_gl(void)
379 {
380 if(!dpy) return;
382 eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
384 if(ctx) {
385 eglDestroyContext(dpy, ctx);
386 ctx = 0;
387 }
388 if(surf) {
389 eglDestroySurface(dpy, surf);
390 surf = 0;
391 }
393 eglTerminate(dpy);
394 dpy = 0;
395 }