diff --git a/.vscode/settings.json b/.vscode/settings.json index eaa918d..0471f99 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "ncurses.h": "c", "stdio.h": "c", "math.h": "c", - "sdl_image.h": "c" + "sdl_image.h": "c", + "display.h": "c" } } \ No newline at end of file diff --git a/bin/back b/bin/back index ab02698..ee18efe 100755 Binary files a/bin/back and b/bin/back differ diff --git a/obj/display.o b/obj/display.o index c78245a..76cd7fa 100644 Binary files a/obj/display.o and b/obj/display.o differ diff --git a/obj/generation.o b/obj/generation.o index 6d4eecf..eb68cf8 100644 Binary files a/obj/generation.o and b/obj/generation.o differ diff --git a/obj/hash.o b/obj/hash.o index 9bd57e8..bc343c1 100644 Binary files a/obj/hash.o and b/obj/hash.o differ diff --git a/obj/main.o b/obj/main.o index 166a11a..50ead5f 100644 Binary files a/obj/main.o and b/obj/main.o differ diff --git a/src/display.c b/src/display.c index 8269b4e..24b6218 100644 --- a/src/display.c +++ b/src/display.c @@ -18,6 +18,12 @@ #include "generation.h" #include "display.h" +int* drawOrder; + +void init_draworder() { + drawOrder = malloc(sizeof(int)*6) ; +} + void updateRenderer(SDL_Renderer* renderer) { //printf("E"); SDL_RenderPresent(renderer); @@ -160,7 +166,7 @@ void drawStringToRenderer(SDL_Renderer* renderer, imgs data, char* s, int X, int // 3D stuff void project_to_camera(double x0, double y0, double z0, double* rx, double* ry, double* rz) { - // align camera to (0, 0, 0) + // align pt to (0, 0, 0) double x = x0 - camx ; double y = y0 - camy ; double z = z0 - camz ; @@ -176,6 +182,23 @@ void project_to_camera(double x0, double y0, double z0, double* rx, double* ry, *rz = zry*cos(rot_vt) + yry*sin(rot_vt) ; } +void rotate_cube(double x0, double y0, double z0, double* rx, double* ry, double* rz, cube_0 cb) { + // align pt to (0, 0, 0) + double x = x0 - (cb.x + cb.w/2) ; + double y = y0 - (cb.y + cb.h/2) ; + double z = z0 - (cb.z + cb.d/2) ; + + // rotate (y) + double xry = x*cos(cb.hz_angle) - z*sin(cb.hz_angle) ; + double yry = y ; + double zry = z*cos(cb.hz_angle) + x*sin(cb.hz_angle) ; + + // rotate (x) + *rx = (cb.x + cb.w/2) + xry ; + *ry = (cb.y + cb.h/2) + yry*cos(cb.vt_angle) - zry*sin(cb.vt_angle) ; + *rz = (cb.z + cb.d/2) + zry*cos(cb.vt_angle) + yry*sin(cb.vt_angle) ; +} + void draw_segment(SDL_Renderer* renderer, double sx, double sy, double sz, double ex, double ey, double ez) { double spx ;double spy ;double spz ;double epx ;double epy ;double epz ; project_to_camera(sx, sy, sz, &spx, &spy, &spz) ; @@ -266,15 +289,15 @@ void drawSegmentRotated(SDL_Renderer* renderer, double sx, double sy, double sz, double pex = ex; double pey = ey; double pez = ez; - axialRotation_Y(&psx, &psz, hz_angle, center_x, center_z); - axialRotation_Y(&pex, &pez, hz_angle, center_x, center_z); + axialRotation_Y(&psx, &psz, -hz_angle, center_x, center_z); + axialRotation_Y(&pex, &pez, -hz_angle, center_x, center_z); + // minus signs cause the base is indirect axialRotation_X(&psy, &psz, vt_angle, center_y, center_z); axialRotation_X(&pey, &pez, vt_angle, center_y, center_z); draw_segment(renderer, psx, psy, psz, pex, pey, pez); } void drawOutlineOfCube_0(SDL_Renderer* renderer, cube_0 c) { - SDL_SetRenderDrawColor(renderer, c.red, c.green, c.blue, 255) ; // x = constant drawSegmentRotated(renderer, c.x, c.y, c.z, c.x + c.w, c.y, c.z, c.hz_angle, c.vt_angle, c.x + c.w/2.0, c.y + c.h/2.0, c.z + c.d/2.0) ; drawSegmentRotated(renderer, c.x, c.y + c.h, c.z, c.x + c.w, c.y + c.h, c.z, c.hz_angle, c.vt_angle, c.x + c.w/2.0, c.y + c.h/2.0, c.z + c.d/2.0) ; @@ -294,12 +317,219 @@ void drawOutlineOfCube_0(SDL_Renderer* renderer, cube_0 c) { drawSegmentRotated(renderer, c.x + c.w, c.y + c.h, c.z, c.x + c.w, c.y + c.h, c.z + c.d, c.hz_angle, c.vt_angle, c.x + c.w/2.0, c.y + c.h/2.0, c.z + c.d/2.0) ; } +// -------------------------------------------------------------------------------------------------------------------------------- // +// this is where the fun begins + +int surfaceDrawOrder(double x0, double y0, double z0, cube_0 cb) { + // returns the number of surfaces that should be drawn, as well as filling drawOrder for said surfaces : + // 0 = +x ; 1 = -x + // 2 = +y ; 3 = -y + // 4 = +z ; 5 = -z + + // align cube center to (0, 0, 0) + double x = x0 - (cb.x + cb.w/2.0) ; + double y = y0 - (cb.y + cb.h/2.0) ; + double z = z0 - (cb.z + cb.d/2.0) ; + // rotate (y) + double xry = x*cos(cb.hz_angle) + z*sin(cb.hz_angle) ; + double yry = y ; + double zry = z*cos(cb.hz_angle) - x*sin(cb.hz_angle) ; + // rotate (x) + double xrx = xry ; + double yrx = yry*cos(cb.vt_angle) - zry*sin(cb.vt_angle) ; + double zrx = zry*cos(cb.vt_angle) + yry*sin(cb.vt_angle) ; + // cube is centered and aligned + int id = 0 ; + if(xrx > cb.w/2.0) { + drawOrder[id] = 0 ; + id += 1 ; + } else if(xrx < -cb.w/2.0) { + drawOrder[id] = 1 ; + id += 1 ; + } + if(yrx > cb.h/2.0) { + drawOrder[id] = 2 ; + id += 1 ; + } else if(yrx < -cb.h/2.0) { + drawOrder[id] = 3 ; + id += 1 ; + } + if(zrx > cb.d/2.0) { + drawOrder[id] = 4 ; + id += 1 ; + } else if(zrx < -cb.d/2.0) { + drawOrder[id] = 5 ; + id += 1 ; + } + if(id == 0) { // inside the cube + for(int k = 0; k < 6; k++) { + drawOrder[k] = k ; + } + return 6; + } else { + return id ; + } +} + +SDL_Vertex construct_vertex(double px, double py, int r, int g, int b) { + SDL_Vertex vtx ; + vtx.color.r = r ; + vtx.color.g = g ; + vtx.color.b = b ; + vtx.color.a = SDL_ALPHA_OPAQUE; + vtx.position.x = (float)px ; + vtx.position.y = (float)py ; + vtx.tex_coord.x = 0.0f; + vtx.tex_coord.y = 0.0f; + return vtx ; +} + +void renderTriangle( + SDL_Renderer* renderer, + double x0, double y0, double z0, + double x1, double y1, double z1, + double x2, double y2, double z2, + int red, int green, int blue +) { + double px0; double py0; double pz0; + double px1; double py1; double pz1; + double px2; double py2; double pz2; + project_to_camera(x0, y0, z0, &px0, &py0, &pz0); + project_to_camera(x1, y1, z1, &px1, &py1, &pz1); + project_to_camera(x2, y2, z2, &px2, &py2, &pz2); + if(pz0 >= 0.4 && pz1 >= 0.4 && pz2 >= 0.4) { + const SDL_Vertex vtxs[3] = { + construct_vertex(1500.0 * (1.0 + (px0 / (1.5 * pz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py0 / (pz0 * tan_fov))) / 2.0, red, green, blue), + construct_vertex(1500.0 * (1.0 + (px1 / (1.5 * pz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py1 / (pz1 * tan_fov))) / 2.0, red, green, blue), + construct_vertex(1500.0 * (1.0 + (px2 / (1.5 * pz2 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py2 / (pz2 * tan_fov))) / 2.0, red, green, blue), + }; + SDL_RenderGeometry(renderer, NULL, vtxs, 3, NULL, 0); + } // TODO // +} + +void renderTriangleRotated( + SDL_Renderer* renderer, + double x0, double y0, double z0, + double x1, double y1, double z1, + double x2, double y2, double z2, + int red, int green, int blue, + cube_0 cb +) { + double px0; double py0; double pz0; + double px1; double py1; double pz1; + double px2; double py2; double pz2; + rotate_cube(x0, y0, z0, &px0, &py0, &pz0, cb); + rotate_cube(x1, y1, z1, &px1, &py1, &pz1, cb); + rotate_cube(x2, y2, z2, &px2, &py2, &pz2, cb); + renderTriangle(renderer, px0, py0, pz0, px1, py1, pz1, px2, py2, pz2, red, green, blue); +} + +void drawSfOfCube(SDL_Renderer* renderer, int sf, cube_0 c) { + if(sf == 0 || sf == 1) { // x + renderTriangleRotated(renderer, + c.x + c.w*(sf==0), c.y, c.z, + c.x + c.w*(sf==0), c.y + c.h, c.z, + c.x + c.w*(sf==0), c.y + c.h, c.z + c.d, + c.red, c.green, c.blue, c + ); + renderTriangleRotated(renderer, + c.x + c.w*(sf==0), c.y, c.z, + c.x + c.w*(sf==0), c.y, c.z + c.d, + c.x + c.w*(sf==0), c.y + c.h, c.z + c.d, + c.red, c.green, c.blue, c + ); + } else if(sf == 2 || sf == 3) { // y + renderTriangleRotated(renderer, + c.x, c.y + c.h*(sf==2), c.z, + c.x + c.w, c.y + c.h*(sf==2), c.z, + c.x + c.w, c.y + c.h*(sf==2), c.z + c.d, + c.red, c.green, c.blue, c + ); + renderTriangleRotated(renderer, + c.x, c.y + c.h*(sf==2), c.z, + c.x, c.y + c.h*(sf==2), c.z + c.d, + c.x + c.w, c.y + c.h*(sf==2), c.z + c.d, + c.red, c.green, c.blue, c + ); + } else { // z + renderTriangleRotated(renderer, + c.x, c.y, c.z + c.d*(sf==4), + c.x + c.w, c.y, c.z + c.d*(sf==4), + c.x + c.w, c.y + c.h, c.z + c.d*(sf==4), + c.red, c.green, c.blue, c + ); + renderTriangleRotated(renderer, + c.x, c.y, c.z + c.d*(sf==4), + c.x, c.y + c.h, c.z + c.d*(sf==4), + c.x + c.w, c.y + c.h, c.z + c.d*(sf==4), + c.red, c.green, c.blue, c + ); + } +} + +void drawFullCube(SDL_Renderer* renderer, cube_0 cb) { + int sfToDraw = surfaceDrawOrder(camx, camy, camz, cb); + for(int k = 0; k < sfToDraw; k++) { + drawSfOfCube(renderer, drawOrder[k], cb); + } +} + +// -------------------------------------------------------------------------------------------------------------------------------- // + +void swap_cb(cube_0* arr, int i, int j) { + cube_0 temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; +} + +void swap_tp(teleporter* arr, int i, int j) { + teleporter temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; +} + +void insertionSort_cb(cube_0* arr, int len) { + for(int k = 0; k < len; k++) { + int j = k-1 ; + while(j >= 0) { + if(distance_pt_cube_0_3d(camx, camy, camz, arr[j]) < distance_pt_cube_0_3d(camx, camy, camz, arr[j+1])) { + swap_cb(arr, j, j+1); + j -= 1; + } else { + j = -1; + } + } + } +} + +void insertionSort_tp(teleporter* arr, int len) { + for(int k = 0; k < len; k++) { + int j = k-1 ; + while(j >= 0) { + if(distance_pt_cube_0_3d(camx, camy, camz, arr[j].hitbox) < distance_pt_cube_0_3d(camx, camy, camz, arr[j+1].hitbox)) { + swap_tp(arr, j, j+1); + j -= 1; + } else { + j = -1; + } + } + } +} + void drawCurrentRoom(SDL_Renderer* renderer) { + insertionSort_cb(current_room->map, current_room->map_size); + insertionSort_tp(current_room->tps, current_room->tps_size); for(int k = 0; k < current_room->map_size; k++) { + SDL_SetRenderDrawColor(renderer, current_room->map[k].red/2, current_room->map[k].green/2, current_room->map[k].blue/2, 255); drawOutlineOfCube_0(renderer, current_room->map[k]); + + drawFullCube(renderer, current_room->map[k]); } for(int k = 0; k < current_room->tps_size; k++) { + SDL_SetRenderDrawColor(renderer, current_room->tps[k].hitbox.red/2, current_room->tps[k].hitbox.green/2, current_room->tps[k].hitbox.blue/2, 255); drawOutlineOfCube_0(renderer, current_room->tps[k].hitbox); + + drawFullCube(renderer, current_room->tps[k].hitbox); } } @@ -310,8 +540,8 @@ void drawData(SDL_Renderer* renderer) { drawNumberToRenderer(renderer, digits, (int)camy, 10, 60, 75/2, 105/2, 0) ; drawNumberToRenderer(renderer, digits, (int)camz, 10, 110, 75/2, 105/2, 0) ; - drawNumberToRenderer(renderer, digits, (int)(rot_hz*180.0/3.14159), 10, 160, 75/2, 105/2, 0) ; - drawNumberToRenderer(renderer, digits, (int)(rot_vt*180.0/3.14159), 10, 210, 75/2, 105/2, 0) ; + drawNumberToRenderer(renderer, digits, (int)(rot_hz*180.0/3.14159), 10, 190, 75/2, 105/2, 0) ; + drawNumberToRenderer(renderer, digits, (int)(rot_vt*180.0/3.14159), 10, 240, 75/2, 105/2, 0) ; drawNumberToRenderer(renderer, digits, player_chx, 310, 10, 75/2, 105/2, 0); drawNumberToRenderer(renderer, digits, player_chy, 310, 60, 75/2, 105/2, 0); diff --git a/src/display.h b/src/display.h index d5baaa6..dd8a3f3 100644 --- a/src/display.h +++ b/src/display.h @@ -1,6 +1,8 @@ #ifndef DISPLAY_H #define DISPLAY_H +void init_draworder(); + void updateRenderer(SDL_Renderer* renderer); void resetRenderer(SDL_Renderer* renderer); @@ -33,4 +35,22 @@ void drawCurrentRoom(SDL_Renderer* renderer); void drawData(SDL_Renderer* renderer); +void renderTriangle( + SDL_Renderer* renderer, + double x0, double y0, double z0, + double x1, double y1, double z1, + double x2, double y2, double z2, + int red, int green, int blue +); +void renderTriangleRotated( + SDL_Renderer* renderer, + double x0, double y0, double z0, + double x1, double y1, double z1, + double x2, double y2, double z2, + int red, int green, int blue, + cube_0 cb +); +void drawSfOfCube(SDL_Renderer* renderer, int sf, cube_0 cb); +void drawFullCube(SDL_Renderer* renderer, cube_0 cb); + #endif \ No newline at end of file diff --git a/src/generation.c b/src/generation.c index aea96a4..df21cb3 100644 --- a/src/generation.c +++ b/src/generation.c @@ -32,7 +32,7 @@ void build_chunk_1(int chx, int chy) { new->tps_size = 4 ; new->map[0] = create_cube_0(0.0, 0.0, 0.0, 5.0, 1.0, 5.0, 0.0, 0.0, 255, 255, 255); - new->map[1] = create_cube_0(0.0, 0.0, 0.0, 5.0, 1.0, 5.0, 3.14159/4.0, 0.0, 255, 255, 255); + new->map[1] = create_cube_0(0.0, 0.0, 0.0, 5.0, 1.0, 5.0, 3.14159/8.0, 0.0, 255, 255, 255); new->map[2] = create_cube_0(0.0, 1.0, 0.0, 1.0, 5.0, 1.0, 0.0, 0.0, 255, 255, 128); new->map[3] = create_cube_0(4.0, 1.0, 0.0, 1.0, 5.0, 1.0, 0.0, 0.0, 255, 255, 128); new->map[4] = create_cube_0(0.0, 1.0, 4.0, 1.0, 5.0, 1.0, 0.0, 0.0, 255, 255, 128); diff --git a/src/main.c b/src/main.c index ec04225..53d7ed5 100644 --- a/src/main.c +++ b/src/main.c @@ -46,16 +46,17 @@ int main(int argc, char** argv) { /* -------------------------------------------------------- */ init_csts() ; init_hashtbl() ; + init_draworder() ; import_digits(rend) ; import_letters(rend) ; while(true) { resetRenderer(rend) ; - SDL_SetRenderDrawColor(rend, 255, 255, 255, 255) ; + SDL_SetRenderDrawColor(rend, 255, 255, 255, SDL_ALPHA_OPAQUE) ; playerActions() ; - drawData(rend) ; generate_nearby_chunks(1); drawCurrentRoom(rend); + drawData(rend) ; updateRenderer(rend) ; usleep(1000000/60) ; diff --git a/src/structure.h b/src/structure.h index 1454d08..21e5022 100644 --- a/src/structure.h +++ b/src/structure.h @@ -81,4 +81,6 @@ extern room* current_room ; extern int player_chx ; extern int player_chy ; +extern int* drawOrder ; + #endif \ No newline at end of file