From e40ab41ae226e257d57a73c69d9bdd8d19f64cb5 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Sat, 2 Apr 2016 15:56:38 +0200 Subject: Better UI (E/H switching). --- src/physics.c | 19 +++++---- src/physics.h | 1 + src/renderer.c | 48 +++++++++------------ src/renderer.h | 20 +++++---- src/ui.c | 133 +++++++++++++++++++++++++++++++++------------------------ 5 files changed, 120 insertions(+), 101 deletions(-) diff --git a/src/physics.c b/src/physics.c index 04c655c..7926478 100644 --- a/src/physics.c +++ b/src/physics.c @@ -34,7 +34,6 @@ void phy_sim_reset(phy_sim *sim) sim->time = 0; sim->running = false; - sim->frame_index = get_time(); } @@ -47,11 +46,11 @@ int phy_sim_create(phy_sim *sim) fi = &sim->field_info; - fi->width = 50; - fi->height = 50; - fi->depth = 50; + fi->width = 100; + fi->height = 100; + fi->depth = 100; fi->spacing = 1.5e10f / max3(fi->width, fi->height, fi->depth); - sim->time_delta = 0.1; + sim->time_delta = 0.2; fi->xstr = 3; fi->ystr = fi->xstr * fi->width; @@ -184,7 +183,8 @@ void phy_sim_add_sources_E(phy_sim *sim) z = fi->depth / 2; E = sim->fields[2].E + z * fi->zstr + y * fi->ystr + x * fi->xstr; - E[0] += exp(-0.1f * pow(sim->time - 5.0f, 2)) * 5; + E[0] += sin(sim->time * 0.5) * + exp(-0.1f * pow(sim->time - 3.0f, 2)) * 50; } void phy_sim_add_sources_H(phy_sim *sim) @@ -198,13 +198,15 @@ void phy_sim_add_sources_H(phy_sim *sim) z = fi->depth / 2; H = sim->fields[2].H + z * fi->zstr + y * fi->ystr + x * fi->xstr; - H[1] -= exp(-0.1f * pow(sim->time - 4.5f, 2)) * 5; + H[1] -= exp(-0.1f * pow(sim->time - 5.0f - sim->time_delta / 2, 2)) * 5; } void phy_sim_step(phy_sim *sim) { phy_field_info *fi = &sim->field_info; phy_field_em *fields = sim->fields, tmp; + int64_t start_time; + start_time = get_time(); phy_sim_step_E(fi, sim->field_mu, sim->time_delta, fields[2].E, fields[0].E, fields[1].H); @@ -222,7 +224,8 @@ void phy_sim_step(phy_sim *sim) { memcpy(fields + 2, &tmp, sizeof(phy_field_em)); sim->time += sim->time_delta; - sim->frame_index = get_time(); + sim->frame_index = get_time(); // for renderer + sim->step_real_time = get_time() - start_time; SDL_mutexV(sim->rotate_lock); } diff --git a/src/physics.h b/src/physics.h index 1ce2a9c..38a6100 100644 --- a/src/physics.h +++ b/src/physics.h @@ -36,6 +36,7 @@ typedef struct { itc_chan ctl; SDL_mutex *rotate_lock; int64_t frame_index; // to avoid re-drawing the same fields + int64_t step_real_time; } phy_sim; void phy_sim_destroy(phy_sim *sim); diff --git a/src/renderer.c b/src/renderer.c index fb1647b..eee6e6d 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -359,39 +359,37 @@ void r_xsection_destroy(r_xsection *xsection) SDL_DestroyTexture(xsection->texture); } -int r_xsection_update(r_window *rw, r_xsection *xsection, - phy_field_info *fi, float *field, int64_t frame_index, - r_xsection_type type, float frac) +int r_xsection_update(r_window *rw, r_xsection *xsection, phy_sim *sim, + int flags, float frac) { + phy_field_info *fi = &sim->field_info; + float *field; size_t width, height, x, y, z; uint8_t *pixels; int pitch; if (xsection->frame_index && - xsection->frame_index == frame_index && - xsection->last_frac == frac && - xsection->last_type == type) + xsection->frame_index == sim->frame_index && + xsection->last_flags == flags && + xsection->last_frac == frac) return 0; // nothing's changed - printf("r_xsection_update: tick %ld\n", frame_index); - - switch (type) { - case XSECTION_XY: + if (flags & XSECTION_XY) { width = fi->width; height = fi->height; - break; - - case XSECTION_XZ: + } else if (flags & XSECTION_XZ) { width = fi->width; height = fi->depth; - break; - - case XSECTION_YZ: + } else { width = fi->height; height = fi->depth; - break; } + if (flags & XSECTION_E) + field = sim->fields[1].E; + else + field = sim->fields[1].H; + if (frac < 0.0f) frac = 0.0f; else if (frac > 1.0f) @@ -404,8 +402,7 @@ int r_xsection_update(r_window *rw, r_xsection *xsection, SDL_LockTexture(xsection->texture, NULL, (void**)&pixels, &pitch); - switch (type) { - case XSECTION_XY: + if (flags & XSECTION_XY) { z = frac * fi->depth; if (z >= fi->depth) z = fi->depth - 1; @@ -423,9 +420,7 @@ int r_xsection_update(r_window *rw, r_xsection *xsection, pixel[1] = r_float_to_u8(point[1]); pixel[2] = r_float_to_u8(point[2]); } - break; - - case XSECTION_XZ: + } else if (flags & XSECTION_XZ) { y = frac * fi->height; if (y >= fi->height) y = fi->height - 1; @@ -443,9 +438,7 @@ int r_xsection_update(r_window *rw, r_xsection *xsection, pixel[1] = r_float_to_u8(point[1]); pixel[2] = r_float_to_u8(point[2]); } - break; - - case XSECTION_YZ: + } else { x = frac * fi->width; if (x >= fi->width) x = fi->width - 1; @@ -463,16 +456,15 @@ int r_xsection_update(r_window *rw, r_xsection *xsection, pixel[1] = r_float_to_u8(point[1]); pixel[2] = r_float_to_u8(point[2]); } - break; } SDL_UnlockTexture(xsection->texture); xsection->aspect_ratio = (float)width / height; + xsection->last_flags = flags; xsection->last_frac = frac; - xsection->last_type = type; - xsection->frame_index = frame_index; + xsection->frame_index = sim->frame_index; return 0; } diff --git a/src/renderer.h b/src/renderer.h index ce373df..fadcd68 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -40,26 +40,28 @@ float r_text_width(float h, char *text); void r_draw_text(r_window *rw, float x, float y, float h, char *text, float *color, int flags); -typedef enum { - XSECTION_XY, - XSECTION_XZ, - XSECTION_YZ -} r_xsection_type; + +#define XSECTION_XY 0x0001 +#define XSECTION_XZ 0x0002 +#define XSECTION_YZ 0x0004 +#define XSECTION_PLANES (XSECTION_XY|XSECTION_XZ|XSECTION_YZ) +#define XSECTION_E 0x0008 +#define XSECTION_H 0x0010 + typedef struct { SDL_Texture *texture; float aspect_ratio; - r_xsection_type last_type; + int last_flags; float last_frac; int64_t frame_index; } r_xsection; void r_xsection_create(r_xsection *xsection); void r_xsection_destroy(r_xsection *xsection); -int r_xsection_update(r_window *rw, r_xsection *xsection, - phy_field_info *fi, float *field, int64_t frame_index, - r_xsection_type type, float frac); +int r_xsection_update(r_window *rw, r_xsection *xsection, phy_sim *sim, + int flags, float frac); void r_xsection_draw(r_window *rw, r_xsection *xsection, float x, float y, float w, float h); diff --git a/src/ui.c b/src/ui.c index 700950b..fac56ce 100644 --- a/src/ui.c +++ b/src/ui.c @@ -25,12 +25,11 @@ typedef struct { phy_sim *sim; bool dragging, selecting; - r_xsection_type xsection_type; + int xsection_flags; float xsection_frac; bool select_valid; vec3_t select; - bool info_valid; int64_t info_time; char info[MAX_INFO]; @@ -137,7 +136,6 @@ void ui_infof(ui_window *uiw, const char *fmt, ...) vsnprintf(uiw->simview.info, MAX_INFO, fmt, vl); va_end(vl); - uiw->simview.info_valid = true; uiw->simview.info_time = get_time(); } @@ -200,15 +198,21 @@ void ui_event_window(SDL_Event *event, ui_window *uiw) case SDL_KEYDOWN: switch (event->key.keysym.sym) { case SDLK_1: - sv->xsection_type = XSECTION_XY; + ui_infof(uiw, "Plaszczyzna przekroju: XY"); + sv->xsection_flags &= ~XSECTION_PLANES; + sv->xsection_flags |= XSECTION_XY; break; case SDLK_2: - sv->xsection_type = XSECTION_XZ; + ui_infof(uiw, "Plaszczyzna przekroju: XZ"); + sv->xsection_flags &= ~XSECTION_PLANES; + sv->xsection_flags |= XSECTION_XZ; break; case SDLK_3: - sv->xsection_type = XSECTION_YZ; + ui_infof(uiw, "Plaszczyzna przekroju: YZ"); + sv->xsection_flags &= ~XSECTION_PLANES; + sv->xsection_flags |= XSECTION_YZ; break; case SDLK_w: @@ -224,20 +228,36 @@ void ui_event_window(SDL_Event *event, ui_window *uiw) break; case SDLK_o: + ui_infof(uiw, "Symulacja wstrzymana"); itc_chan_push(&sv->sim->ctl, PHY_CMD_PAUSE, NULL); break; case SDLK_p: + ui_infof(uiw, "Symulacja wznowiona"); itc_chan_push(&sv->sim->ctl, PHY_CMD_RESUME, NULL); break; case SDLK_l: + ui_infof(uiw, "Pojedyńczy krok"); itc_chan_push(&sv->sim->ctl, PHY_CMD_STEP, NULL); break; case SDLK_r: + ui_infof(uiw, "Symulacja wyzerowana"); itc_chan_push(&sv->sim->ctl, PHY_CMD_RESET, NULL); break; + + case SDLK_4: + ui_infof(uiw, "Przekrój: pola elektrycznego"); + sv->xsection_flags &= ~XSECTION_H; + sv->xsection_flags |= XSECTION_E; + break; + + case SDLK_5: + ui_infof(uiw, "Przekrój: pola magnetycznego"); + sv->xsection_flags &= ~XSECTION_E; + sv->xsection_flags |= XSECTION_H; + break; } } } @@ -287,7 +307,7 @@ void ui_animate_exp(float *val, float targ, float lambda, float dt) *val = targ + (*val - targ) * exp(-lambda * dt); } -void ui_draw_simview_xsection(ui_window *uiw, float *field) +void ui_draw_simview_xsection(ui_window *uiw) { ui_simview *sv = &uiw->simview; phy_sim *sim = sv->sim; @@ -295,8 +315,7 @@ void ui_draw_simview_xsection(ui_window *uiw, float *field) vec2_t origin_s, scale_s; SDL_mutexP(sim->rotate_lock); - r_xsection_update(uiw->rw, &sv->xsection, &sim->field_info, field, - sim->frame_index, sv->xsection_type, + r_xsection_update(uiw->rw, &sv->xsection, sim, sv->xsection_flags, sv->xsection_frac); SDL_mutexV(sim->rotate_lock); @@ -336,22 +355,15 @@ void ui_draw_simview_selection(ui_window *uiw) return; } - switch (sv->xsection_type) { - case XSECTION_XY: + if (sv->xsection_flags & XSECTION_XY) v3_set(sv->select, select_2d[0], select_2d[1], sv->xsection_frac); - break; - - case XSECTION_XZ: + else if (sv->xsection_flags & XSECTION_XZ) v3_set(sv->select, select_2d[0], sv->xsection_frac, select_2d[1]); - break; - - case XSECTION_YZ: + else v3_set(sv->select, sv->xsection_frac, select_2d[0], select_2d[1]); - break; - } sv->select_valid = true; } @@ -359,19 +371,12 @@ void ui_draw_simview_selection(ui_window *uiw) if (!sv->select_valid) return; - switch (sv->xsection_type) { - case XSECTION_XY: + if (sv->xsection_flags & XSECTION_XY) v2_set(select_s, sv->select[0], sv->select[1]); - break; - - case XSECTION_XZ: + else if (sv->xsection_flags & XSECTION_XZ) v2_set(select_s, sv->select[0], sv->select[2]); - break; - - case XSECTION_YZ: + else v2_set(select_s, sv->select[1], sv->select[2]); - break; - } v2_mul_mst2(select_s, select_s, sv->tf_x2s); @@ -381,19 +386,28 @@ void ui_draw_simview_selection(ui_window *uiw) theme.color_select); } -void ui_draw_simview_bars(ui_window *uiw, float dt) +char *ui_draw_simview_top_bar_text(ui_simview *sv) { - const char *xsection_type_strings[] = { - "Przekrój XY przez Z", - "Przekrój XZ przez Y", - "Przekrój YZ przez X" - }; + int flags = sv->xsection_flags; + + va("Przekrój %s płaszczyzną %s=%f", + (flags & XSECTION_E ? "E" : + "H"), + (flags & XSECTION_XY ? "Z" : + flags & XSECTION_XZ ? "Y" : + "X"), + sv->xsection_frac); +} +void ui_draw_simview_bars(ui_window *uiw, float dt) +{ ui_simview *sv = &uiw->simview; phy_sim *sim = sv->sim; phy_field_em *field_em = sim->fields + 1; phy_field_info *fi = &sim->field_info; + SDL_mutexP(sim->rotate_lock); + // upper sv->margin_top = theme.font_size; @@ -401,13 +415,11 @@ void ui_draw_simview_bars(ui_window *uiw, float dt) r_draw_rect(uiw->rw, 0, 0, uiw->w, theme.font_size, theme.color_main); r_draw_text(uiw->rw, uiw->w, 0, theme.font_size, - va("%.0fkl./s %04zu", 1.0f / dt, uiw->frame_count % 10000), - theme.color_text_light, TEXT_RIGHTX); + va("%.0fkl./s", 1.0f / dt), theme.color_text_light, + TEXT_RIGHTX); r_draw_text(uiw->rw, 0, 0, theme.font_size, - va("%s = %f", xsection_type_strings[sv->xsection_type], - sv->xsection_frac), - theme.color_text, 0); + ui_draw_simview_top_bar_text(sv), theme.color_text, 0); // lower @@ -416,8 +428,15 @@ void ui_draw_simview_bars(ui_window *uiw, float dt) uiw->w, theme.font_size, theme.color_main); r_draw_text(uiw->rw, 0, uiw->h - theme.font_size, - theme.font_size, va("t = %f", sim->time), - theme.color_text, 0); + theme.font_size, va("t = %f, Δt = %f", sim->time, + sim->time_delta), theme.color_text, 0); + + r_draw_text(uiw->rw, uiw->w, uiw->h - theme.font_size, + theme.font_size, va("%.3fs/krok", + (sim->step_real_time * 1.0e-9f)), + theme.color_text_light, TEXT_RIGHTX); + + if (sv->select_valid) { size_t x, y, z, offs; @@ -447,21 +466,15 @@ void ui_draw_simview_bars(ui_window *uiw, float dt) field_em->H[offs], field_em->H[offs + 1], field_em->H[offs + 2]), theme.color_text, 0); } -} + SDL_mutexV(sim->rotate_lock); +} -void ui_draw_simview(ui_window *uiw, int64_t time, float dt) +void ui_draw_simview_info(ui_window *uiw, int64_t time) { - ui_draw_simview_xsection(uiw, uiw->simview.sim->fields[1].E); - ui_draw_simview_selection(uiw); - ui_draw_simview_bars(uiw, dt); - - // status - - // info text + ui_simview *sv = &uiw->simview; -/* - if (sv->info_valid && sv->info_time + 2000000000ll > time) + if (sv->info_time && sv->info_time + 2000000000ll > time) { vec4_t color; @@ -480,7 +493,15 @@ void ui_draw_simview(ui_window *uiw, int64_t time, float dt) r_draw_text(uiw->rw, uiw->w / 2.0f, theme.font_size, theme.font_size, sv->info, color, TEXT_CENTERX); - }*/ + } +} + +void ui_draw_simview(ui_window *uiw, int64_t time, float dt) +{ + ui_draw_simview_xsection(uiw); + ui_draw_simview_selection(uiw); + ui_draw_simview_bars(uiw, dt); + ui_draw_simview_info(uiw, time); } void ui_draw_window(ui_window *uiw) @@ -497,14 +518,14 @@ void ui_draw_window(ui_window *uiw) v2_set(sv->origin, 0, 0); v2_set(sv->scale, 1, 1); - sv->xsection_type = XSECTION_XY; + sv->xsection_flags = XSECTION_XY | XSECTION_E; sv->xsection_frac = 0.5f; sv->select_valid = false; sv->margin_top = theme.font_size; sv->margin_bottom = 0; - sv->info_valid = false; + sv->info_time = 0; r_clear(uiw->rw, r_color_black); return; -- cgit