rendering of multiple slices per frame
parent
f0cf492919
commit
9ec8da15b1
106
src/main.c
106
src/main.c
|
@ -3,8 +3,9 @@
|
||||||
#define ANTIALIASING true
|
#define ANTIALIASING true
|
||||||
#define WHWIDTH 18
|
#define WHWIDTH 18
|
||||||
#define DITHERFACTOR 85
|
#define DITHERFACTOR 85
|
||||||
#define LINES_PER_CHUNK 100
|
#define MAX_LINES_PER_CHUNK 100
|
||||||
#define FRAME_DURATION 35
|
#define FRAME_DURATION 500
|
||||||
|
#define ANGLE_INCREMENT 3
|
||||||
|
|
||||||
static uint8_t bayer8x8[] = {
|
static uint8_t bayer8x8[] = {
|
||||||
0,32, 8,40, 2,34,10,42,
|
0,32, 8,40, 2,34,10,42,
|
||||||
|
@ -35,6 +36,10 @@ typedef struct {
|
||||||
uint32_t timer_timeout;
|
uint32_t timer_timeout;
|
||||||
uint16_t animation_angle;
|
uint16_t animation_angle;
|
||||||
GPoint center;
|
GPoint center;
|
||||||
|
GRect texturebounds;
|
||||||
|
GBitmap *texture;
|
||||||
|
GSize texturesize;
|
||||||
|
GColor bgcolor;
|
||||||
} State;
|
} State;
|
||||||
|
|
||||||
// global state
|
// global state
|
||||||
|
@ -44,11 +49,11 @@ static bool debug = true;
|
||||||
|
|
||||||
/************************************ UI **************************************/
|
/************************************ UI **************************************/
|
||||||
|
|
||||||
static void render_part(State *state, Layer *layer, GContext *ctx) {
|
static void create_texture(State *state, Layer *layer, GContext *ctx) {
|
||||||
GRect bounds = layer_get_bounds(layer);
|
GRect bounds = layer_get_bounds(layer);
|
||||||
GRect 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(texturebounds, GEdgeInsets(9));
|
GRect bounds_mo = grect_inset(state->texturebounds, GEdgeInsets(9));
|
||||||
GRect bounds_ho = grect_inset(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;
|
||||||
|
@ -71,49 +76,70 @@ static void render_part(State *state, Layer *layer, GContext *ctx) {
|
||||||
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);
|
||||||
|
|
||||||
// START OF TEXTURE MAPPING
|
state->bgcolor = GColorIcterine; // background color for behind the objects
|
||||||
GColor bgcolor = GColorIcterine; // background color for behind the objects
|
|
||||||
|
|
||||||
|
// set up texture buffer
|
||||||
|
state->texturesize = GSize(state->texturebounds.size.w, state->texturebounds.size.h);
|
||||||
|
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);
|
||||||
|
|
||||||
|
// capture frame buffer
|
||||||
|
GBitmap *tex_fb = graphics_capture_frame_buffer(ctx);
|
||||||
|
|
||||||
|
// capture texture before starting to modify the frame buffer
|
||||||
|
for(uint8_t y = 0; y < bounds.size.h; y++) {
|
||||||
|
GBitmapDataRowInfo info = gbitmap_get_data_row_info(tex_fb, y);
|
||||||
|
for(uint8_t x = info.min_x; x <= info.max_x; x++) {
|
||||||
|
if (x >= state->texturebounds.origin.x && y >= state->texturebounds.origin.y && x < state->texturebounds.origin.x+state->texturebounds.size.w && y < state->texturebounds.origin.y+state->texturebounds.size.h) {
|
||||||
|
texture_matrix[y-state->texturebounds.origin.y][x-state->texturebounds.origin.x] = info.data[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// release frame buffer
|
||||||
|
graphics_release_frame_buffer(ctx, tex_fb);
|
||||||
|
|
||||||
|
graphics_context_set_fill_color(ctx, GColorBlack);
|
||||||
|
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_texture(State *state) {
|
||||||
|
// free memory
|
||||||
|
gbitmap_destroy(state->texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void render_slice(State *state, Layer *layer, GContext *ctx, GRect renderbounds) {
|
||||||
|
GRect bounds = layer_get_bounds(layer);
|
||||||
|
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; }
|
||||||
|
uint8_t (*texture_matrix)[state->texturesize.w] = (uint8_t (*)[state->texturesize.w]) gbitmap_get_data(state->texture);
|
||||||
|
|
||||||
|
// 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);
|
||||||
size_t lut_res_size = 144*LINES_PER_CHUNK*2;
|
size_t lut_res_size = bounds.size.w*renderbounds.size.h*2;
|
||||||
uint8_t *lut_buffer = (uint8_t*)malloc(lut_res_size);
|
uint8_t *lut_buffer = (uint8_t*)malloc(lut_res_size);
|
||||||
resource_load_byte_range(lut_handle, 0, lut_buffer, lut_res_size);
|
resource_load_byte_range(lut_handle, renderbounds.origin.y*bounds.size.w*2, lut_buffer, lut_res_size);
|
||||||
|
|
||||||
ResHandle shad_handle = resource_get_handle(RESOURCE_ID_SHADING_TEST);
|
ResHandle shad_handle = resource_get_handle(RESOURCE_ID_SHADING_TEST);
|
||||||
size_t shad_res_size = 144*LINES_PER_CHUNK;
|
size_t shad_res_size = 144*renderbounds.size.h;
|
||||||
uint8_t *shad_buffer = (uint8_t*)malloc(shad_res_size);
|
uint8_t *shad_buffer = (uint8_t*)malloc(shad_res_size);
|
||||||
resource_load_byte_range(shad_handle, 0, shad_buffer, shad_res_size);
|
resource_load_byte_range(shad_handle, renderbounds.origin.y*bounds.size.w, shad_buffer, shad_res_size);
|
||||||
|
|
||||||
// define mapping metadata
|
// define mapping metadata
|
||||||
GSize mapdimensions = GSize(144, LINES_PER_CHUNK);
|
GSize mapdimensions = GSize(bounds.size.w, renderbounds.size.h);
|
||||||
//GPoint master_offset = GPoint(state->center.x-(mapdimensions.w/2), state->center.y-(mapdimensions.h/2)+4);
|
//GPoint master_offset = GPoint(state->center.x-(mapdimensions.w/2), state->center.y-(mapdimensions.h/2)+4);
|
||||||
GPoint master_offset = GPoint(0, 0);
|
GPoint master_offset = GPoint(bounds.origin.x, renderbounds.origin.y);
|
||||||
GRect mapbounds = GRect(master_offset.x, master_offset.y, mapdimensions.w, mapdimensions.h);
|
GRect mapbounds = GRect(master_offset.x, master_offset.y, mapdimensions.w, mapdimensions.h);
|
||||||
|
|
||||||
// capture frame buffer
|
// capture frame buffer
|
||||||
GBitmap *fb = graphics_capture_frame_buffer(ctx);
|
GBitmap *fb = graphics_capture_frame_buffer(ctx);
|
||||||
|
|
||||||
// set up texture buffer
|
|
||||||
GSize texturesize = GSize(texturebounds.size.w, texturebounds.size.h);
|
|
||||||
GBitmap *texture = gbitmap_create_blank(texturesize, GBitmapFormat8Bit);
|
|
||||||
uint8_t (*texture_matrix)[texturesize.w] = (uint8_t (*)[texturesize.w]) gbitmap_get_data(texture);
|
|
||||||
|
|
||||||
// capture texture before starting to modify the frame buffer
|
|
||||||
for(uint8_t y = 0; y < bounds.size.h; y++) {
|
|
||||||
GBitmapDataRowInfo info = gbitmap_get_data_row_info(fb, y);
|
|
||||||
for(uint8_t x = info.min_x; x <= info.max_x; x++) {
|
|
||||||
if (x >= texturebounds.origin.x && y >= texturebounds.origin.y && x < texturebounds.origin.x+texturebounds.size.w && y < texturebounds.origin.y+texturebounds.size.h) {
|
|
||||||
texture_matrix[y-texturebounds.origin.y][x-texturebounds.origin.x] = info.data[x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// render texture mapped and shaded object
|
// render texture mapped and shaded object
|
||||||
for(uint8_t y = 0; y < bounds.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);
|
||||||
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 = bgcolor;
|
GColor fbpixel = state->bgcolor;
|
||||||
|
|
||||||
// convert to 24 bit color
|
// convert to 24 bit color
|
||||||
GColor32 newpixel;
|
GColor32 newpixel;
|
||||||
|
@ -185,12 +211,20 @@ static void render_part(State *state, Layer *layer, GContext *ctx) {
|
||||||
// free memory
|
// free memory
|
||||||
free(lut_buffer);
|
free(lut_buffer);
|
||||||
free(shad_buffer);
|
free(shad_buffer);
|
||||||
gbitmap_destroy(texture);
|
|
||||||
|
|
||||||
// release frame buffer
|
// release frame buffer
|
||||||
graphics_release_frame_buffer(ctx, fb);
|
graphics_release_frame_buffer(ctx, fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void render_frame(State *state, Layer *layer, GContext *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, 56));
|
||||||
|
render_slice(state, layer, ctx, GRect(0, 56, 144, 56));
|
||||||
|
render_slice(state, layer, ctx, GRect(0, 112, 144, 56));
|
||||||
|
destroy_texture(state);
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************** App **************************************/
|
/*********************************** App **************************************/
|
||||||
|
|
||||||
void animation_init(State* state) {
|
void animation_init(State* state) {
|
||||||
|
@ -201,12 +235,12 @@ void animation_init(State* state) {
|
||||||
state->center.y -= 1;
|
state->center.y -= 1;
|
||||||
}
|
}
|
||||||
static void animation_layer_update(Layer *layer, GContext *ctx) {
|
static void animation_layer_update(Layer *layer, GContext *ctx) {
|
||||||
render_part(&g, layer, ctx);
|
render_frame(&g, layer, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void animation_update(void* data) {
|
void animation_update(void* data) {
|
||||||
State* state = (State*)data;
|
State* state = (State*)data;
|
||||||
state->animation_angle += (state->animation_angle < 360) ? 1 : 0-state->animation_angle;
|
state->animation_angle += (state->animation_angle < 360) ? ANGLE_INCREMENT : 0-state->animation_angle;
|
||||||
layer_mark_dirty(state->layer);
|
layer_mark_dirty(state->layer);
|
||||||
state->timer = app_timer_register(state->timer_timeout, &animation_update, data);
|
state->timer = app_timer_register(state->timer_timeout, &animation_update, data);
|
||||||
}
|
}
|
||||||
|
@ -242,7 +276,3 @@ int main() {
|
||||||
app_event_loop();
|
app_event_loop();
|
||||||
deinit();
|
deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue