diff --git a/CMakeLists.txt b/CMakeLists.txt index 02ec700..56a750e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,8 @@ set(SOURCES src/generator/gen1.cpp src/generator/gen2.cpp src/generator/gen3.cpp - src/level.cpp) + src/level.cpp + src/render.cpp) set(ASSETS) fxconv_declare_assets(${ASSETS} WITH_METADATA) diff --git a/src/main.cpp b/src/main.cpp index 75ed008..c55dbb4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,69 +1,67 @@ #include "level.h" #include "generator.h" -#include -#include - -int main(void) -{ - level_t level = level_create(1); - - while (1) { - level_update(&level); - - //TODO: display - dclear(C_WHITE); - level_display(&level); - dupdate(); - - clearevents(); - if(keydown(KEY_EXIT) || keydown(KEY_MENU)) break; - if(keydown(KEY_EXE)) { - level_advance(&level); - } - if (keydown(KEY_F1)) level = level_create(1); - if (keydown(KEY_F2)) level = level_create(2); - if (keydown(KEY_F3)) level = level_create(3); - } - - return 0; -} - -#if 0 +#include "render.h" #include #include #include #include #include -#include +#include + int main(void) { + __printf_enable_fp(); prof_init(); azrp_config_scale(1); azrp_shader_clear_configure(); -/* azrp_shader_image_rgb16_configure(); - azrp_shader_image_p8_configure(); - azrp_shader_image_p4_configure(); */ +// azrp_shader_image_rgb16_configure(); +// azrp_shader_image_p8_configure(); +// azrp_shader_image_p4_configure(); azrp_shader_triangle_configure(); - int volatile need_frame = 1; + level_t level = level_create(1); + +/* int volatile need_frame = 1; int timer = timer_configure(TIMER_ANY, 33000, GINT_CALL_SET(&need_frame)); timer_start(timer); + float t = 0.0; */ - float t = 0.0; + bool game_run = true; + while(game_run) { +/* float dt = 1.0 / 30; + t += dt; */ - while(1) { - float dt = 1.0 / 30; - t += dt; - - int y1 = (int)(90 * sin(t + 0.05)) + 100; - int y2 = (int)(90 * sin(t + 1.05)) + 100; - int y3 = (int)(90 * sin(t + 2.05)) + 100; + level_update(&level); + // TODO: display azrp_perf_clear(); - azrp_clear(C_WHITE); - azrp_triangle(10, y1, 128, y2, 380, y3, C_RED); +// dclear(C_WHITE); + + struct camera camera; + camera.pos = vec3(0, RENDER_CAMERA_DEPTH, 0); + vec2 screen_size(DWIDTH, DHEIGHT); + + for(int i = 0; i < PLATFORM_COUNT; i++) { + int gray = i * 31 / PLATFORM_COUNT; + int color = C_RGB(gray, gray, gray); + + struct prect p = render_platform_position(i, num(3.0)); + camera_project_prect(&camera, &p, screen_size); + render_triangle(&p.nl, &p.fr, &p.fl, color); + render_triangle(&p.fr, &p.nl, &p.nr, color); + +/* dprint(4, i*14+4, C_BLACK, + "%d (%d): nl=%d/%d nr=%d/%d z=%d|%d", + i, gray, + (int)p.nl.x, (int)p.nl.y, + (int)p.nr.x, (int)p.nr.y, + (int)p.nl.z, (int)p.fl.z); + extern float get_near_plane(void); + dprint(4, 180, C_BLACK, "FOV=%g", get_near_plane()); */ + } azrp_update(); +// dupdate(); drect(0, DHEIGHT-20, DWIDTH-1, DHEIGHT-1, C_WHITE); dprint(1, 210, C_BLACK, "cmdgen:%03dus sort:%03dus render:%4d+%4dus", @@ -73,13 +71,26 @@ int main(void) prof_time(azrp_perf_r61524)); r61524_display(gint_vram, DHEIGHT-20, 20, R61524_DMA_WAIT); - //--- +// level_display(&level); - clearevents(); - if(keydown(KEY_EXIT) || keydown(KEY_MENU)) break; + key_event_t ev; + while((ev = pollevent()).type != KEYEV_NONE) { + if(ev.type == KEYEV_UP) + continue; + + if(ev.key == KEY_EXIT || ev.key == KEY_MENU) + game_run = false; + if(ev.key == KEY_EXE) + level_advance(&level); + if(ev.key == KEY_F1) + level = level_create(1); + if(ev.key == KEY_F2) + level = level_create(2); + if(ev.key == KEY_F3) + level = level_create(3); + } } - timer_stop(timer); - return 1; +// timer_stop(timer); + return 0; } -#endif diff --git a/src/render.cpp b/src/render.cpp new file mode 100644 index 0000000..75f45ec --- /dev/null +++ b/src/render.cpp @@ -0,0 +1,86 @@ +#define __BSD_VISIBLE 1 +#include "level.h" +#include "render.h" +#include +#include + +/* Angle span for a platform in the level cylinder */ +static float get_alpha(void) +{ + return 2 * 3.14159 / PLATFORM_COUNT; +} + +/* Get enlargement factor from FOV */ +float get_near_plane(void) +{ + float fov_radians = RENDER_FOV * 3.14159 / 180; + return 2 * atanf(1 / fov_radians); +} + +vec3 vec_rotate_around_z(vec3 v, float angle) +{ + float sin_f, cos_f; + sincosf(angle, &sin_f, &cos_f); + num s=sin_f, c=cos_f; + + vec3 u; + u.x = c * v.x - s * v.y; + u.y = c * v.y + s * v.x; + u.z = v.z; + return u; +} + +struct prect render_platform_position(int platform_id, num z) +{ + struct prect r; + float alpha = get_alpha(); + vec3 radius(0, RENDER_RADIUS, 0); + + /* +/- rather than -/+ because right-handed system */ + float angle_l = alpha * platform_id + (alpha / 2); + float angle_r = alpha * platform_id - (alpha / 2); + + r.nl = r.fl = vec_rotate_around_z(radius, angle_l); + r.nr = r.fr = vec_rotate_around_z(radius, angle_r); + + r.nl.z += z; + r.nr.z += z; + r.fl.z += z + RENDER_SECTION_LENGTH; + r.fr.z += z + RENDER_SECTION_LENGTH; + return r; +} + +vec3 camera_project(struct camera *camera, vec3 u, vec2 screen_size) +{ + u -= camera->pos; + if(u.z <= 0) + return u; + + static float near_plane = get_near_plane(); + + int screen = screen_size.x < screen_size.y + ? (int)screen_size.x / 2 + : (int)screen_size.y / 2; + + u.x = u.x * num(near_plane) * screen / u.z + screen_size.x / 2; + u.y = u.y * num(near_plane) * screen / u.z + screen_size.y / 2; + return u; +} + +void camera_project_prect(struct camera *camera, struct prect *p, + vec2 screen_size) +{ + p->nl = camera_project(camera, p->nl, screen_size); + p->nr = camera_project(camera, p->nr, screen_size); + p->fl = camera_project(camera, p->fl, screen_size); + p->fr = camera_project(camera, p->fr, screen_size); +} + +void render_triangle(vec3 *p1, vec3 *p2, vec3 *p3, int color) +{ + azrp_triangle( + (int)p1->x, (int)p1->y, + (int)p2->x, (int)p2->y, + (int)p3->x, (int)p3->y, + color); +} diff --git a/src/render.h b/src/render.h new file mode 100644 index 0000000..75102b6 --- /dev/null +++ b/src/render.h @@ -0,0 +1,36 @@ +#ifndef __RENDERH__ +# define __RENDERH__ + +#include +#include +using namespace libnum; + +/* Vertical FOV, in degrees */ +#define RENDER_FOV 120.0 +/* Radius of the level cylinder, in world units */ +#define RENDER_RADIUS num(4.0) +/* Camera depth in the level cylinder, in world units */ +#define RENDER_CAMERA_DEPTH (RENDER_RADIUS / 2) +/* Section lengths, in world units */ +#define RENDER_SECTION_LENGTH num(4.0) + +struct prect { + vec3 nl, nr; /* Near left and near right points */ + vec3 fl, fr; /* Far left and far right points */ +}; + +struct prect render_platform_position(int platform_id, num z); + +/* We assume the camera is looking towards (0,0,z) */ +struct camera { + vec3 pos; +}; + +vec3 camera_project(struct camera *camera, vec3 u, vec2 screen_size); + +void camera_project_prect(struct camera *camera, struct prect *p, + vec2 screen_size); + +void render_triangle(vec3 *p1, vec3 *p2, vec3 *p3, int color); + +#endif /* __RENDERH__ */