fixed a crash on actual hardware
parent
9ec8da15b1
commit
1fca55e8f2
|
@ -1,3 +1,7 @@
|
||||||
|
#pebble
|
||||||
|
/build
|
||||||
|
.lock-waf_darwin_build
|
||||||
|
|
||||||
# Object files
|
# Object files
|
||||||
*.o
|
*.o
|
||||||
*.ko
|
*.ko
|
||||||
|
|
61
src/main.c
61
src/main.c
|
@ -3,9 +3,9 @@
|
||||||
#define ANTIALIASING true
|
#define ANTIALIASING true
|
||||||
#define WHWIDTH 18
|
#define WHWIDTH 18
|
||||||
#define DITHERFACTOR 85
|
#define DITHERFACTOR 85
|
||||||
#define MAX_LINES_PER_CHUNK 100
|
#define MAX_LINES_PER_SLICE 100
|
||||||
#define FRAME_DURATION 500
|
#define FRAME_DURATION 70
|
||||||
#define ANGLE_INCREMENT 3
|
#define ANGLE_INCREMENT 4
|
||||||
|
|
||||||
static uint8_t bayer8x8[] = {
|
static uint8_t bayer8x8[] = {
|
||||||
0,32, 8,40, 2,34,10,42,
|
0,32, 8,40, 2,34,10,42,
|
||||||
|
@ -45,7 +45,7 @@ typedef struct {
|
||||||
// global state
|
// global state
|
||||||
static State g;
|
static State g;
|
||||||
|
|
||||||
static bool debug = true;
|
static bool debug = false;
|
||||||
|
|
||||||
/************************************ UI **************************************/
|
/************************************ UI **************************************/
|
||||||
|
|
||||||
|
@ -54,38 +54,38 @@ static void create_texture(State *state, Layer *layer, GContext *ctx) {
|
||||||
state->texturebounds = GRect(state->center.x-64, state->center.y-64, 127, 127);
|
state->texturebounds = GRect(state->center.x-64, state->center.y-64, 127, 127);
|
||||||
GRect bounds_mo = grect_inset(state->texturebounds, GEdgeInsets(9));
|
GRect bounds_mo = grect_inset(state->texturebounds, GEdgeInsets(9));
|
||||||
GRect bounds_ho = grect_inset(state->texturebounds, GEdgeInsets(23));
|
GRect bounds_ho = grect_inset(state->texturebounds, GEdgeInsets(23));
|
||||||
|
|
||||||
uint16_t minute_deg = state->animation_angle;
|
uint16_t minute_deg = state->animation_angle;
|
||||||
uint16_t hour_deg = 360-minute_deg;
|
uint16_t hour_deg = 360-minute_deg;
|
||||||
GPoint minute_hand_outer = gpoint_from_polar(bounds_mo, GOvalScaleModeFillCircle, DEG_TO_TRIGANGLE(minute_deg));
|
GPoint minute_hand_outer = gpoint_from_polar(bounds_mo, GOvalScaleModeFillCircle, DEG_TO_TRIGANGLE(minute_deg));
|
||||||
GPoint hour_hand_outer = gpoint_from_polar(bounds_ho, GOvalScaleModeFillCircle, DEG_TO_TRIGANGLE(hour_deg));
|
GPoint hour_hand_outer = gpoint_from_polar(bounds_ho, GOvalScaleModeFillCircle, DEG_TO_TRIGANGLE(hour_deg));
|
||||||
|
|
||||||
// draw the watch hands that will be used as texture
|
// draw the watch hands that will be used as texture
|
||||||
graphics_context_set_antialiased(ctx, ANTIALIASING);
|
graphics_context_set_antialiased(ctx, ANTIALIASING);
|
||||||
graphics_context_set_fill_color(ctx, GColorShockingPink);
|
graphics_context_set_fill_color(ctx, GColorShockingPink);
|
||||||
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
|
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
|
||||||
|
|
||||||
graphics_context_set_stroke_color(ctx, GColorCobaltBlue);
|
graphics_context_set_stroke_color(ctx, GColorCobaltBlue);
|
||||||
graphics_context_set_stroke_width(ctx, WHWIDTH);
|
graphics_context_set_stroke_width(ctx, WHWIDTH);
|
||||||
graphics_draw_line(ctx, state->center, minute_hand_outer);
|
graphics_draw_line(ctx, state->center, minute_hand_outer);
|
||||||
|
|
||||||
graphics_context_set_stroke_color(ctx, GColorCeleste);
|
graphics_context_set_stroke_color(ctx, GColorCeleste);
|
||||||
graphics_context_set_stroke_width(ctx, WHWIDTH);
|
graphics_context_set_stroke_width(ctx, WHWIDTH);
|
||||||
graphics_draw_line(ctx, state->center, hour_hand_outer);
|
graphics_draw_line(ctx, state->center, hour_hand_outer);
|
||||||
|
|
||||||
graphics_context_set_fill_color(ctx, GColorBlack);
|
graphics_context_set_fill_color(ctx, GColorBlack);
|
||||||
graphics_fill_circle(ctx, state->center, WHWIDTH/4);
|
graphics_fill_circle(ctx, state->center, WHWIDTH/4);
|
||||||
|
|
||||||
state->bgcolor = GColorIcterine; // background color for behind the objects
|
state->bgcolor = GColorIcterine; // background color for behind the objects
|
||||||
|
|
||||||
// set up texture buffer
|
// set up texture buffer
|
||||||
state->texturesize = GSize(state->texturebounds.size.w, state->texturebounds.size.h);
|
state->texturesize = GSize(state->texturebounds.size.w, state->texturebounds.size.h);
|
||||||
state->texture = gbitmap_create_blank(state->texturesize, GBitmapFormat8Bit);
|
state->texture = gbitmap_create_blank(state->texturesize, GBitmapFormat8Bit);
|
||||||
uint8_t (*texture_matrix)[state->texturesize.w] = (uint8_t (*)[state->texturesize.w]) gbitmap_get_data(state->texture);
|
uint8_t (*texture_matrix)[state->texturesize.w] = (uint8_t (*)[state->texturesize.w]) gbitmap_get_data(state->texture);
|
||||||
|
|
||||||
// capture frame buffer
|
// capture frame buffer
|
||||||
GBitmap *tex_fb = graphics_capture_frame_buffer(ctx);
|
GBitmap *tex_fb = graphics_capture_frame_buffer(ctx);
|
||||||
|
|
||||||
// capture texture before starting to modify the frame buffer
|
// capture texture before starting to modify the frame buffer
|
||||||
for(uint8_t y = 0; y < bounds.size.h; y++) {
|
for(uint8_t y = 0; y < bounds.size.h; y++) {
|
||||||
GBitmapDataRowInfo info = gbitmap_get_data_row_info(tex_fb, y);
|
GBitmapDataRowInfo info = gbitmap_get_data_row_info(tex_fb, y);
|
||||||
|
@ -95,10 +95,10 @@ static void create_texture(State *state, Layer *layer, GContext *ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// release frame buffer
|
// release frame buffer
|
||||||
graphics_release_frame_buffer(ctx, tex_fb);
|
graphics_release_frame_buffer(ctx, tex_fb);
|
||||||
|
|
||||||
graphics_context_set_fill_color(ctx, GColorBlack);
|
graphics_context_set_fill_color(ctx, GColorBlack);
|
||||||
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
|
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
|
||||||
}
|
}
|
||||||
|
@ -111,9 +111,8 @@ static void destroy_texture(State *state) {
|
||||||
static void render_slice(State *state, Layer *layer, GContext *ctx, GRect renderbounds) {
|
static void render_slice(State *state, Layer *layer, GContext *ctx, GRect renderbounds) {
|
||||||
GRect bounds = layer_get_bounds(layer);
|
GRect bounds = layer_get_bounds(layer);
|
||||||
if (renderbounds.origin.y < bounds.origin.y) { renderbounds.origin.y = bounds.origin.y; }
|
if (renderbounds.origin.y < bounds.origin.y) { renderbounds.origin.y = bounds.origin.y; }
|
||||||
if (renderbounds.size.h > MAX_LINES_PER_CHUNK) { renderbounds.size.h = MAX_LINES_PER_CHUNK; }
|
if (renderbounds.size.h > MAX_LINES_PER_SLICE) { renderbounds.size.h = MAX_LINES_PER_SLICE; }
|
||||||
uint8_t (*texture_matrix)[state->texturesize.w] = (uint8_t (*)[state->texturesize.w]) gbitmap_get_data(state->texture);
|
uint8_t (*texture_matrix)[state->texturesize.w] = (uint8_t (*)[state->texturesize.w]) gbitmap_get_data(state->texture);
|
||||||
|
|
||||||
// START OF TEXTURE MAPPING
|
// START OF TEXTURE MAPPING
|
||||||
// load map parts
|
// load map parts
|
||||||
ResHandle lut_handle = resource_get_handle(RESOURCE_ID_MAP_TEST);
|
ResHandle lut_handle = resource_get_handle(RESOURCE_ID_MAP_TEST);
|
||||||
|
@ -138,6 +137,7 @@ static void render_slice(State *state, Layer *layer, GContext *ctx, GRect render
|
||||||
// render texture mapped and shaded object
|
// render texture mapped and shaded object
|
||||||
for(uint8_t y = renderbounds.origin.y; y < renderbounds.origin.y+renderbounds.size.h; y++) {
|
for(uint8_t y = renderbounds.origin.y; y < renderbounds.origin.y+renderbounds.size.h; y++) {
|
||||||
GBitmapDataRowInfo info = gbitmap_get_data_row_info(fb, y);
|
GBitmapDataRowInfo info = gbitmap_get_data_row_info(fb, y);
|
||||||
|
//APP_LOG(APP_LOG_LEVEL_DEBUG, "y %d x <= %d", y, info.max_x);
|
||||||
for(uint8_t x = info.min_x; x <= info.max_x; x++) {
|
for(uint8_t x = info.min_x; x <= info.max_x; x++) {
|
||||||
GColor fbpixel = state->bgcolor;
|
GColor fbpixel = state->bgcolor;
|
||||||
|
|
||||||
|
@ -154,15 +154,26 @@ static void render_slice(State *state, Layer *layer, GContext *ctx, GRect render
|
||||||
|
|
||||||
uint8_t xpos = lut_buffer[surfindex*2];
|
uint8_t xpos = lut_buffer[surfindex*2];
|
||||||
uint8_t ypos = lut_buffer[(surfindex*2)+1];
|
uint8_t ypos = lut_buffer[(surfindex*2)+1];
|
||||||
|
|
||||||
|
|
||||||
|
//APP_LOG(APP_LOG_LEVEL_DEBUG, "x %d - y %d", xpos, ypos);
|
||||||
if (xpos > 0 || ypos > 0) {
|
if (xpos > 0 || ypos > 0) {
|
||||||
uint8_t texturexpos = xpos/2;
|
uint8_t texturexpos = xpos/2;
|
||||||
uint8_t textureypos = 127-(ypos/2);
|
uint8_t textureypos = 127-(ypos/2);
|
||||||
|
if (textureypos > state->texturesize.h-1) {
|
||||||
|
textureypos = state->texturesize.h-1;
|
||||||
|
}
|
||||||
|
if (texturexpos > state->texturesize.w-1) {
|
||||||
|
texturexpos = state->texturesize.w-1;
|
||||||
|
}
|
||||||
|
//APP_LOG(APP_LOG_LEVEL_DEBUG, "texturex %d - texturey %d", texturexpos, textureypos);
|
||||||
GColor texturepixel = (GColor8) texture_matrix[textureypos][texturexpos];
|
GColor texturepixel = (GColor8) texture_matrix[textureypos][texturexpos];
|
||||||
newpixel.r = texturepixel.r*DITHERFACTOR;
|
newpixel.r = texturepixel.r*DITHERFACTOR;
|
||||||
newpixel.g = texturepixel.g*DITHERFACTOR;
|
newpixel.g = texturepixel.g*DITHERFACTOR;
|
||||||
newpixel.b = texturepixel.b*DITHERFACTOR;
|
newpixel.b = texturepixel.b*DITHERFACTOR;
|
||||||
|
|
||||||
if (xpos%2 == 1 || ypos%2 == 1) {
|
if (xpos%2 == 1 || ypos%2 == 1) {
|
||||||
// interpolate
|
// interpolation
|
||||||
GColor texturepixel2;
|
GColor texturepixel2;
|
||||||
if (texturexpos < 255 && xpos%2 == 1) {
|
if (texturexpos < 255 && xpos%2 == 1) {
|
||||||
texturepixel2.argb = texture_matrix[textureypos][texturexpos+1];
|
texturepixel2.argb = texture_matrix[textureypos][texturexpos+1];
|
||||||
|
@ -218,10 +229,8 @@ static void render_slice(State *state, Layer *layer, GContext *ctx, GRect render
|
||||||
|
|
||||||
static void render_frame(State *state, Layer *layer, GContext *ctx) {
|
static void render_frame(State *state, Layer *layer, GContext *ctx) {
|
||||||
create_texture(state, layer, ctx);
|
create_texture(state, layer, ctx);
|
||||||
// TODO fix crash on real hardware when slice lines start or end outside some sort of unknown safe zone
|
render_slice(state, layer, ctx, GRect(0, 0, 144, 84));
|
||||||
render_slice(state, layer, ctx, GRect(0, 0, 144, 56));
|
render_slice(state, layer, ctx, GRect(0, 84, 144, 84));
|
||||||
render_slice(state, layer, ctx, GRect(0, 56, 144, 56));
|
|
||||||
render_slice(state, layer, ctx, GRect(0, 112, 144, 56));
|
|
||||||
destroy_texture(state);
|
destroy_texture(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,16 +259,16 @@ static void init() {
|
||||||
window_stack_push(g.window, true);
|
window_stack_push(g.window, true);
|
||||||
Layer* window_layer = window_get_root_layer(g.window);
|
Layer* window_layer = window_get_root_layer(g.window);
|
||||||
GRect window_frame = layer_get_frame(window_layer);
|
GRect window_frame = layer_get_frame(window_layer);
|
||||||
|
|
||||||
g.layer = layer_create(window_frame);
|
g.layer = layer_create(window_frame);
|
||||||
layer_set_update_proc(g.layer, &animation_layer_update);
|
layer_set_update_proc(g.layer, &animation_layer_update);
|
||||||
layer_add_child(window_layer, g.layer);
|
layer_add_child(window_layer, g.layer);
|
||||||
|
|
||||||
animation_init(&g);
|
animation_init(&g);
|
||||||
|
|
||||||
g.timer_timeout = FRAME_DURATION;
|
g.timer_timeout = FRAME_DURATION;
|
||||||
g.timer = app_timer_register(g.timer_timeout, &animation_update, &g);
|
g.timer = app_timer_register(g.timer_timeout, &animation_update, &g);
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
light_enable(true);
|
light_enable(true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue