static void utime_update(const char* name, double* _t0) { double t1 = a3d_utime(); #ifdef DEBUG_TIME LOGI("%s dt=%lf", name, t1 - *_t0); #endif *_t0 = t1; }
void loax_server_resize(loax_server_t* self, int w, int h) { assert(self); LOGI("%ix%i", w, h); self->w = w; self->h = h; int type = LOAX_EVENT_RESIZE; double utime = a3d_utime(); net_socket_sendall(self->socket_event, (const void*) &type, sizeof(int)); net_socket_sendall(self->socket_event, (const void*) &utime, sizeof(double)); net_socket_sendall(self->socket_event, (const void*) &w, sizeof(int)); net_socket_sendall(self->socket_event, (const void*) &h, sizeof(int)); net_socket_flush(self->socket_event); }
static void lzs_renderer_step(lzs_renderer_t* self) { assert(self); LOGD("debug"); double t = a3d_utime(); double dt0 = t - self->t0; ++self->frames; // don't update fps every frame if(dt0 >= 1.0 * A3D_USEC) { double seconds = dt0 / A3D_USEC; double fps = (double) self->frames / seconds; // LOGI("%i frames in %.2lf seconds = %.2lf FPS", self->frames, seconds, fps); a3d_texstring_printf(self->string_fps, "%i fps", (int) fps); self->t0 = t; self->frames = 0; } }
void lzs_renderer_draw(lzs_renderer_t* self) { assert(self); LOGD("debug"); double t0 = a3d_utime(); // stretch screen to 800x480 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(0.0f, SCREEN_W, SCREEN_H, 0.0f, 0.0f, 2.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // draw camera glEnable(GL_TEXTURE_EXTERNAL_OES); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindTexture(GL_TEXTURE_EXTERNAL_OES, self->texid); glVertexPointer(3, GL_FLOAT, 0, VERTEX); glTexCoordPointer(2, GL_FLOAT, 0, COORDS); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_EXTERNAL_OES); utime_update("setup", &t0); // capture buffers GLint format = TEXGZ_BGRA; GLint type = GL_UNSIGNED_BYTE; glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &format); glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &type); if((format == TEXGZ_BGRA) && (type == GL_UNSIGNED_BYTE)) { LOGD("readpixels format=0x%X, type=0x%X", format, type); // TODO - check for texgz errors // process buffers texgz_tex_t* bc = self->buffer_color; texgz_tex_t* bg = self->buffer_gray; texgz_tex_t* bsx = self->buffer_sx; texgz_tex_t* bsy = self->buffer_sy; glReadPixels(self->sphero_x - RADIUS_BALL, (SCREEN_H - self->sphero_y - 1) - RADIUS_BALL, bc->width, bc->height, bc->format, bc->type, (void*) bc->pixels); #ifdef DEBUG_BUFFERS texgz_tex_export(bc, "/sdcard/laser-shark/color.texgz"); #endif utime_update("readpixels", &t0); texgz_tex_computegray(bc, bg); utime_update("computegray", &t0); texgz_tex_computeedges3x3(bg, bsx, bsy); utime_update("computeedges", &t0); // compute peak { int x; int y; int peak_x = 0; int peak_y = 0; float peak = 0.0f; float* gpixels = (float*) bg->pixels; float* xpixels = (float*) bsx->pixels; float* ypixels = (float*) bsy->pixels; for(x = 0; x < bg->width; ++x) { for(y = 0; y < bg->height; ++y) { int idx = bg->width*y + x; // compute magnitude squared float magsq = xpixels[idx]*xpixels[idx] + ypixels[idx]*ypixels[idx]; gpixels[idx] = magsq; if(magsq > peak) { peak_x = x; peak_y = y; peak = magsq; } } } LOGD("peak=%f, peak_x=%i, peak_y=%i", peak, peak_x, peak_y); utime_update("computepeak", &t0); #ifdef DEBUG_BUFFERS texgz_tex_export(bg, "/sdcard/laser-shark/peak.texgz"); #endif // move sphero center to match peak self->sphero_x += (float) peak_x - (float) bg->width / 2.0f; self->sphero_y -= (float) peak_y - (float) bg->height / 2.0f; } } else { LOGE("unsupported format=0x%X, type=0x%X", format, type); } // compute phone X, Y center compute_position(self, SCREEN_CX, SCREEN_CY, &self->phone_X, &self->phone_Y); // compute sphero X, Y compute_position(self, self->sphero_x, self->sphero_y, &self->sphero_X, &self->sphero_Y); utime_update("computeposition", &t0); // compute goal float dx = self->phone_X - self->sphero_X; float dy = self->phone_Y - self->sphero_Y; float a = fix_angle(atan2f(dx, dy) * 180.0f / M_PI); self->sphero_goal = a - self->sphero_heading_offset; // compute speed float dotp = cosf((a - self->sphero_heading) * M_PI / 180.0f); if(dotp > 0.0f) { // linearly interpolate speed based on the turning angle self->sphero_speed = SPEED_MAX*dotp + SPEED_MIN*(1.0f - dotp); } else { // go slow to turn around self->sphero_speed = SPEED_MIN; } // draw camera cross-hair { float x = SCREEN_CX; float y = SCREEN_CY; float r = RADIUS_CROSS; limit_position(r, &x, &y); lzs_renderer_crosshair(y - r, x - r, y + r, x + r, 1.0f, 0.0f, 0.0f); } // draw sphero search box { float r = RADIUS_BALL; limit_position(r, &self->sphero_x, &self->sphero_y); float x = self->sphero_x; float y = self->sphero_y; lzs_renderer_drawbox(y - r, x - r, y + r, x + r, 0.0f, 1.0f, 0.0f, 0); } lzs_renderer_step(self); // draw string a3d_texstring_printf(self->string_sphero, "sphero: head=%i, x=%0.1f, y=%0.1f, spd=%0.2f, goal=%i", (int) fix_angle(self->sphero_heading + self->sphero_heading_offset), self->sphero_X, self->sphero_Y, self->sphero_speed, (int) fix_angle(self->sphero_goal)); a3d_texstring_printf(self->string_phone, "phone: heading=%i, slope=%i, x=%0.1f, y=%0.1f", (int) fix_angle(self->phone_heading), (int) fix_angle(self->phone_slope), self->phone_X, self->phone_Y); a3d_texstring_draw(self->string_sphero, 400.0f, 16.0f, 800, 480); a3d_texstring_draw(self->string_phone, 400.0f, 16.0f + self->string_sphero->size, 800, 480); a3d_texstring_draw(self->string_fps, (float) SCREEN_W - 16.0f, (float) SCREEN_H - 16.0f, SCREEN_W, SCREEN_H); utime_update("draw", &t0); //texgz_tex_t* screen = texgz_tex_new(SCREEN_W, SCREEN_H, SCREEN_W, SCREEN_H, TEXGZ_UNSIGNED_BYTE, TEXGZ_BGRA, NULL); //glReadPixels(0, 0, screen->width, screen->height, screen->format, screen->type, (void*) screen->pixels); //texgz_tex_export(screen, "/sdcard/laser-shark/screen.texgz"); //texgz_tex_delete(&screen); A3D_GL_GETERROR(); }
lzs_renderer_t* lzs_renderer_new(const char* font) { assert(s); LOGD("debug"); lzs_renderer_t* self = (lzs_renderer_t*) malloc(sizeof(lzs_renderer_t)); if(self == NULL) { LOGE("malloc failed"); return NULL; } self->sphero_x = 400.0f; self->sphero_y = 240.0f; self->sphero_X = 0.0f; self->sphero_Y = 0.0f; self->sphero_speed = 0.0f; self->sphero_heading = 0.0f; self->sphero_heading_offset = 0.0f; self->sphero_goal = 0.0f; self->phone_heading = 0.0f; self->phone_slope = 0.0f; self->phone_height = 5.0f; self->t0 = a3d_utime(); self->frames = 0; // allocate the buffer(s) GLint bsize = 2 * ((int) RADIUS_BALL); GLint format = TEXGZ_BGRA; GLint type = TEXGZ_UNSIGNED_BYTE; self->buffer_color = texgz_tex_new(bsize, bsize, bsize, bsize, type, format, NULL); if(self->buffer_color == NULL) { goto fail_color; } format = TEXGZ_LUMINANCE; type = TEXGZ_FLOAT; self->buffer_gray = texgz_tex_new(bsize, bsize, bsize, bsize, type, format, NULL); if(self->buffer_gray == NULL) { goto fail_gray; } self->buffer_sx = texgz_tex_new(bsize, bsize, bsize, bsize, type, format, NULL); if(self->buffer_sx == NULL) { goto fail_sx; } self->buffer_sy = texgz_tex_new(bsize, bsize, bsize, bsize, type, format, NULL); if(self->buffer_sy == NULL) { goto fail_sy; } // create the font self->font = a3d_texfont_new(font); if(self->font == NULL) { goto fail_font; } // create the string(s) self->string_sphero = a3d_texstring_new(self->font, 64, 24, A3D_TEXSTRING_TOP_CENTER, 1.0f, 1.0f, 0.235f, 1.0f); if(self->string_sphero == NULL) { goto fail_string_sphero; } self->string_phone = a3d_texstring_new(self->font, 64, 24, A3D_TEXSTRING_TOP_CENTER, 1.0f, 1.0f, 0.235f, 1.0f); if(self->string_phone == NULL) { goto fail_string_phone; } self->string_fps = a3d_texstring_new(self->font, 16, 24, A3D_TEXSTRING_BOTTOM_RIGHT, 1.0f, 1.0f, 0.235f, 1.0f); if(self->string_fps == NULL) { goto fail_string_fps; } glGenTextures(1, &self->texid); glEnableClientState(GL_VERTEX_ARRAY); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glDisable(GL_DEPTH_TEST); // success return self; // failure fail_string_fps: a3d_texstring_delete(&self->string_phone); fail_string_phone: a3d_texstring_delete(&self->string_sphero); fail_string_sphero: a3d_texfont_delete(&self->font); fail_font: texgz_tex_delete(&self->buffer_sy); fail_sy: texgz_tex_delete(&self->buffer_sx); fail_sx: texgz_tex_delete(&self->buffer_gray); fail_gray: texgz_tex_delete(&self->buffer_color); fail_color: free(self); return NULL; }