#include #include #include #include #include #include #include #include #include #include #include #include #include "hash.h" #include "structure.h" #include "base.h" #include "triangles.h" #include "move.h" #include "entities.h" #include "generation.h" #include "display.h" int flashlight = 0 ; int MAX_SIZE = 8192 ; int* drawOrder; double draw_constant ; pt_2d** triangles_to_render ; pt_2d** triangles_og_coords ; //double* triangles_areas ; int triangles_i ; int* reds ; int* greens ; int* blues ; int* triangles_order ; bool* visited_tri ; int visited_i ; void init_draworder() { drawOrder = malloc(sizeof(int)*6) ; draw_constant = 0.4 ; triangles_to_render = malloc(sizeof(pt_2d*)*MAX_SIZE) ; triangles_og_coords = malloc(sizeof(pt_2d*)*MAX_SIZE) ; reds = malloc(sizeof(int)*MAX_SIZE) ; greens = malloc(sizeof(int)*MAX_SIZE) ; blues = malloc(sizeof(int)*MAX_SIZE) ; triangles_order = malloc(sizeof(int)*MAX_SIZE) ; //triangles_areas = malloc(sizeof(double)*MAX_SIZE) ; visited_tri = malloc(sizeof(bool)*MAX_SIZE) ; for(int k = 0; k < MAX_SIZE; k++) { triangles_to_render[k] = malloc(sizeof(pt_2d)*3); triangles_og_coords[k] = malloc(sizeof(pt_2d)*3); triangles_order[k] = k; } triangles_i = 0; visited_i = 0; } void updateRenderer(SDL_Renderer* renderer) { //printf("E"); SDL_RenderPresent(renderer); } void resetRenderer(SDL_Renderer* renderer) { SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); } void drawRectToRenderer(SDL_Renderer* renderer, SDL_Rect* rect, int R, int G, int B, int A) { SDL_SetRenderDrawColor(renderer, R, G, B, A); SDL_RenderFillRect(renderer, rect); } void placeRectToRenderer(SDL_Renderer* renderer, int X, int Y, int W, int H, int R, int G, int B, int A) { SDL_Rect rect; rect.x = X; rect.y = Y; rect.w = W; rect.h = H; SDL_SetRenderDrawColor(renderer, R, G, B, A); SDL_RenderFillRect(renderer, &rect); } void placeRectToRendererNoColor(SDL_Renderer* renderer, int X, int Y, int W, int H) { SDL_Rect rect; rect.x = X; rect.y = Y; rect.w = W; rect.h = H; SDL_RenderFillRect(renderer, &rect); } void drawLineWithThicc(SDL_Renderer* renderer, int width, int x1, int x2, int y1, int y2, int R, int G, int B, int A) { // draws line with width (native SDL cannot do that) double theta = 0.0; double seglen = distance_pt_pt_3d(x1, y1, 0.0, x2, y2, 0.0); while(theta < 1.0) { placeRectToRenderer(renderer, convex_seg(x1, x2, theta)-width/2, convex_seg(y1, y2, theta)-width/2, width, width, R, G, B, A); theta += 1 / seglen; } } void drawLineWithThiccNoColor(SDL_Renderer* renderer, int width, int x1, int x2, int y1, int y2) { // draws line with width (native SDL cannot do that) double theta = 0.0; double seglen = distance_pt_pt_3d(x1, y1, 0.0, x2, y2, 0.0); while(theta < 1.0) { placeRectToRendererNoColor(renderer, convex_seg(x1, x2, theta)-width/2, convex_seg(y1, y2, theta)-width/2, width, width); theta += 1 / seglen; } } void drawLineWithThiccGradient(SDL_Renderer* renderer, int start_width, int end_width, int x1, int x2, int y1, int y2, int R, int G, int B, int A) { // draws line with width ; // width goes from start_width to end_with in a linear way double theta = 0.0; double seglen = distance_pt_pt_3d(x1, y1, 0.0, x2, y2, 0.0); while(theta < 1.0) { int width = convex_seg(start_width, end_width, theta) ; placeRectToRenderer(renderer, convex_seg(x1, x2, theta)-width/2, convex_seg(y1, y2, theta)-width/2, width, width, R, G, B, A); theta += 1 / seglen; } } void drawDigitToRenderer(SDL_Renderer* renderer, imgs data, int digit, int X, int Y, int W, int H) { if(digit == -727) { SDL_Rect rect; rect.x = X; rect.y = Y; rect.w = W; rect.h = H; SDL_Texture* texture = data.arr[10]; SDL_RenderCopy(renderer, texture, NULL, &rect); } else if (!(0 <= digit && digit <= 9)) { fprintf(stderr, "Illegal digit : '%d'.\n", digit); exit(1); } else { SDL_Rect rect; rect.x = X; rect.y = Y; rect.w = W; rect.h = H; SDL_Texture* texture = data.arr[digit]; SDL_RenderCopy(renderer, texture, NULL, &rect); } } void drawCharToRenderer(SDL_Renderer* renderer, imgs data, char c, int X, int Y, int W, int H) { if ((int)c >= 97 && (int)c <= 122) { SDL_Rect rect; rect.x = X; rect.y = Y; rect.w = W; rect.h = H; SDL_Texture* texture = data.arr[(int)c - 97]; SDL_RenderCopy(renderer, texture, NULL, &rect); } } void drawNumberToRenderer(SDL_Renderer* renderer, imgs data, int n, int X, int Y, int W, int H, int Woffset) { if(n == 0) { drawDigitToRenderer(renderer, data, 0, X + W, Y, W, H); } else if(n > 0) { int toDraw = 0, remaining = n, nIter = ln_baseN(n, 10); while(nIter != 0) { toDraw = remaining%10; remaining = remaining / 10; drawDigitToRenderer(renderer, data, toDraw, X + (W-Woffset)*nIter, Y, W, H); nIter--; } } else { int toDraw = 0, remaining = -n, nIter = ln_baseN(-n, 10); drawDigitToRenderer(renderer, data, -727, X, Y, W, H); while(nIter != 0) { toDraw = remaining%10; remaining = remaining / 10; drawDigitToRenderer(renderer, data, toDraw, X + (W-Woffset)*nIter, Y, W, H); nIter--; } } } void drawStringToRenderer(SDL_Renderer* renderer, imgs data, char* s, int X, int Y, int W, int H) { int k = 0 ; while(s[k] != '\0') { drawCharToRenderer(renderer, data, s[k], X + W*k, Y, W, H); k += 1; } } // ---------------------------------------------------------------------------------------------------------------------------------- // // 3D stuff double pt_z_distance_to_camera(double x, double y, double z) { double ret ; project_to_camera(x, y, z, NULL, NULL, &ret) ; return absf(ret) ; } double segment_z_distance_to_camera(double x0, double y0, double z0, double x1, double y1, double z1) { double ret0 = pt_z_distance_to_camera(x0, y0, z0); double ret1 = pt_z_distance_to_camera(x1, y1, z1); double theta = -( ((x1 - x0) * (x0 - camx) + (y1 - y0) * (y0 - camy) + (z1 - z0) * (z0 - camz)) / ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) + (z1 - z0) * (z1 - z0)) ); // projection factor of camera onto the line return absf(convex_pt(ret0, ret1, mind(maxd(theta, 0.0), 1.0))); } double square_z_distance_to_camera( double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2 ) { return maxd(segment_z_distance_to_camera(x0, y0, z0, x1, y1, z1), segment_z_distance_to_camera(x0, y0, z0, x2, y2, z2)); } double cube_z_distance_to_camera(cube_0 cb) { double dist_0 = square_z_distance_to_camera( cb.x + cb.w, cb.y, cb.z, cb.x + cb.w, cb.y + cb.h, cb.z, cb.x + cb.w, cb.y, cb.z + cb.d ); double dist_1 = square_z_distance_to_camera( cb.x, cb.y, cb.z, cb.x, cb.y + cb.h, cb.z, cb.x, cb.y, cb.z + cb.d ); double dist_2 = square_z_distance_to_camera( cb.x, cb.y + cb.h, cb.z, cb.x + cb.w, cb.y + cb.h, cb.z, cb.x, cb.y + cb.h, cb.z + cb.d ); double dist_3 = square_z_distance_to_camera( cb.x, cb.y, cb.z, cb.x + cb.w, cb.y, cb.z, cb.x, cb.y, cb.z + cb.d ); double dist_4 = square_z_distance_to_camera( cb.x, cb.y, cb.z + cb.d, cb.x + cb.w, cb.y, cb.z + cb.d, cb.x, cb.y + cb.h, cb.z + cb.d ); double dist_5 = square_z_distance_to_camera( cb.x, cb.y, cb.z, cb.x + cb.w, cb.y, cb.z, cb.x, cb.y + cb.h, cb.z ); return maxd(maxd(dist_0, dist_1), maxd(maxd(dist_2, dist_3), maxd(dist_4, dist_5))); } // ---------------------------------------------------------------------------------------------------------------------------------- // 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) ; project_to_camera(ex, ey, ez, &epx, &epy, &epz) ; if(spz >= draw_constant && epz >= draw_constant) { drawLineWithThiccNoColor(renderer, 1, (int)(1500.0 * (1.0 + (spx / (1.5 * spz * tan_fov))) / 2.0), (int)(1500.0 * (1.0 + (epx / (1.5 * epz * tan_fov))) / 2.0), (int)(1000.0 * (1.0 + (spy / (spz * tan_fov))) / 2.0), (int)(1000.0 * (1.0 + (epy / (epz * tan_fov))) / 2.0) ) ; } else if(epz >= draw_constant) { double midx = convex_pt(ex, sx, (epz - draw_constant)/(epz - spz)) ; double midy = convex_pt(ey, sy, (epz - draw_constant)/(epz - spz)) ; double midz = convex_pt(ez, sz, (epz - draw_constant)/(epz - spz)) ; project_to_camera(midx, midy, midz, &spx, &spy, &spz) ; //printf("* %f\n", spz) ; drawLineWithThiccNoColor(renderer, 1, (int)(1500.0 * (1.0 + (spx / (1.5 * spz * tan_fov))) / 2.0), (int)(1500.0 * (1.0 + (epx / (1.5 * epz * tan_fov))) / 2.0), (int)(1000.0 * (1.0 + (spy / (spz * tan_fov))) / 2.0), (int)(1000.0 * (1.0 + (epy / (epz * tan_fov))) / 2.0) ) ; } else if(spz >= draw_constant) { double midx = convex_pt(sx, ex, (spz - draw_constant)/(spz - epz)) ; double midy = convex_pt(sy, ey, (spz - draw_constant)/(spz - epz)) ; double midz = convex_pt(sz, ez, (spz - draw_constant)/(spz - epz)) ; project_to_camera(midx, midy, midz, &epx, &epy, &epz) ; //printf("%f *\n", epz) ; drawLineWithThiccNoColor(renderer, 1, (int)(1500.0 * (1.0 + (spx / (1.5 * spz * tan_fov))) / 2.0), (int)(1500.0 * (1.0 + (epx / (1.5 * epz * tan_fov))) / 2.0), (int)(1000.0 * (1.0 + (spy / (spz * tan_fov))) / 2.0), (int)(1000.0 * (1.0 + (epy / (epz * tan_fov))) / 2.0) ) ; } // else : not visible (behind camera) } void axialRotation_X0(double* y, double* z, double theta) { double y0 = *y ; *y = (*y)*cos(theta) - (*z)*sin(theta) ; *z = (*z)*cos(theta) + y0*sin(theta) ; } void axialRotation_X(double* y, double* z, double theta, double cst_y, double cst_z) { // project the space onto the (y, z) plane to get cst_y and cst_z double y1 = *y - cst_y; double z1 = *z - cst_z; axialRotation_X0(&y1, &z1, theta); *y = y1 + cst_y ; *z = z1 + cst_z ; } void axialRotation_Y0(double* x, double* z, double theta) { double x0 = *x ; *x = (*x)*cos(theta) + (*z)*sin(theta) ; *z = (*z)*cos(theta) - x0*sin(theta) ; } void axialRotation_Y(double* x, double* z, double theta, double cst_x, double cst_z) { // project the space onto the (y, z) plane to get cst_y and cst_z double x1 = *x - cst_x; double z1 = *z - cst_z; axialRotation_Y0(&x1, &z1, theta); *x = x1 + cst_x ; *z = z1 + cst_z ; } void axialRotation_Z0(double* x, double* y, double theta) { double x0 = *x ; *x = (*x)*cos(theta) - (*y)*sin(theta) ; *y = (*y)*cos(theta) + x0*sin(theta) ; } void axialRotation_Z(double* x, double* y, double theta, double cst_x, double cst_y) { // project the space onto the (y, z) plane to get cst_y and cst_z double x1 = *x - cst_x; double y1 = *y - cst_y; axialRotation_Z0(&x1, &y1, theta); *x = x1 + cst_x ; *y = y1 + cst_y ; } void drawSegmentRotated(SDL_Renderer* renderer, double sx, double sy, double sz, double ex, double ey, double ez, double hz_angle, double vt_angle, double center_x, double center_y, double center_z) { double psx = sx; double psy = sy; double psz = 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); // 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) { // 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) ; drawSegmentRotated(renderer, c.x, c.y, c.z + c.d, c.x + c.w, c.y, 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) ; drawSegmentRotated(renderer, c.x, c.y + c.h, c.z + c.d, 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) ; // y = constant drawSegmentRotated(renderer, c.x, c.y, c.z, c.x, 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) ; drawSegmentRotated(renderer, c.x + c.w, c.y, 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) ; drawSegmentRotated(renderer, c.x, c.y, c.z + c.d, c.x, 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) ; drawSegmentRotated(renderer, c.x + c.w, c.y, c.z + c.d, 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) ; // z = constant drawSegmentRotated(renderer, c.x, c.y, c.z, c.x, c.y, 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) ; drawSegmentRotated(renderer, c.x + c.w, c.y, c.z, c.x + c.w, c.y, 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) ; drawSegmentRotated(renderer, c.x, c.y + c.h, c.z, c.x, 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) ; 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, int a) { SDL_Vertex vtx ; vtx.color.r = r ; vtx.color.g = g ; vtx.color.b = b ; vtx.color.a = a ; 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 renderTriangleNoProject( SDL_Renderer* renderer, double px0, double py0, double pz0, double px1, double py1, double pz1, double px2, double py2, double pz2, int red, int green, int blue, bool debug ) { const SDL_Vertex vtxs[3] = { construct_vertex(px0, py0, max(red - (int)(flashlight*pz0), 0), max(green - (int)(flashlight*pz0), 0), max(blue - (int)(flashlight*pz0), 0), 255), construct_vertex(px1, py1, max(red - (int)(flashlight*pz1), 0), max(green - (int)(flashlight*pz1), 0), max(blue - (int)(flashlight*pz1), 0), 255), construct_vertex(px2, py2, max(red - (int)(flashlight*pz2), 0), max(green - (int)(flashlight*pz2), 0), max(blue - (int)(flashlight*pz2), 0), 255), }; if(debug) { printf("P[*] : (%f, %f), (%f, %f), (%f, %f)\n", vtxs[0].position.x, vtxs[0].position.y, vtxs[1].position.x, vtxs[1].position.y, vtxs[2].position.x, vtxs[2].position.y); } SDL_RenderGeometry(renderer, NULL, vtxs, 3, NULL, 0); } double near = -1.0 ; double far = 1.0 ; double getZbuffer(double x, double y, double z) { return sqrt(x*x + y*y + z*z); //return z; //return (2.0*(z - near)/(far - near) -1.0); //return ((far + near)/(far - near) + (1.0/z)*((-2.0*far*near)/(far - near))); } pt_2d to_pt_2d(double x0, double y0, double z0) { pt_2d res; res.x = x0; res.y = y0; res.z = z0; return res; } bool inside_fov(double px, double py) { return true ; } pt_2d bounding_box_botleft(int k) { pt_2d res; res.x = mind(triangles_to_render[k][0].x, mind(triangles_to_render[k][1].x, triangles_to_render[k][2].x)); res.y = mind(triangles_to_render[k][0].y, mind(triangles_to_render[k][1].y, triangles_to_render[k][2].y)); return res; } pt_2d bounding_box_topright(int k) { pt_2d res; res.x = maxd(triangles_to_render[k][0].x, maxd(triangles_to_render[k][1].x, triangles_to_render[k][2].x)); res.y = maxd(triangles_to_render[k][0].y, maxd(triangles_to_render[k][1].y, triangles_to_render[k][2].y)); return res; } bool bbox_inside_cam(int k) { pt_2d btl = bounding_box_botleft(k); pt_2d tpr = bounding_box_topright(k); return !(tpr.x <= 0.0 || btl.x >= 1500.0 || tpr.y <= 0.0 || btl.y >= 1000.0); } void addTriangle( 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; double fpx0; double fpy0; double fpz0; double fpx1; double fpy1; double fpz1; double mpx0; double mpy0; double mpz0; double mpx1; double mpy1; double mpz1; double mx0, my0, mz0, mx1, my1, mz1; 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(inside_fov(px0, py0) || inside_fov(px1, py1) || inside_fov(px2, py2)) { if(pz0 >= draw_constant && pz1 >= draw_constant && pz2 >= draw_constant) { triangles_to_render[triangles_i][0] = to_pt_2d(1500.0 * (1.0 + (px0 / (1.5 * pz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py0 / (pz0 * tan_fov))) / 2.0, getZbuffer(px0, py0, pz0)); triangles_to_render[triangles_i][1] = to_pt_2d(1500.0 * (1.0 + (px1 / (1.5 * pz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py1 / (pz1 * tan_fov))) / 2.0, getZbuffer(px1, py1, pz1)); triangles_to_render[triangles_i][2] = to_pt_2d(1500.0 * (1.0 + (px2 / (1.5 * pz2 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py2 / (pz2 * tan_fov))) / 2.0, getZbuffer(px2, py2, pz2)); if(bbox_inside_cam(triangles_i)) { triangles_og_coords[triangles_i][0] = to_pt_2d(px0, py0, pz0); triangles_og_coords[triangles_i][1] = to_pt_2d(px1, py1, pz1); triangles_og_coords[triangles_i][2] = to_pt_2d(px2, py2, pz2); //triangles_areas[triangles_i] = area_of_triangle(triangles_to_render[triangles_i]); reds[triangles_i] = red ; greens[triangles_i] = green ; blues[triangles_i] = blue ; triangles_i += 1; } } else if((pz0 >= draw_constant) + (pz1 >= draw_constant) + (pz2 >= draw_constant) == 2) { if(pz0 < draw_constant) { // pz1 >= draw_constant and pz2 >+ draw_constant fpx0 = px1 ; fpy0 = py1 ; fpz0 = pz1 ; fpx1 = px2 ; fpy1 = py2 ; fpz1 = pz2 ; mx0 = convex_pt(x1, x0, (pz1 - draw_constant)/(pz1 - pz0)); my0 = convex_pt(y1, y0, (pz1 - draw_constant)/(pz1 - pz0)); mz0 = convex_pt(z1, z0, (pz1 - draw_constant)/(pz1 - pz0)); mx1 = convex_pt(x2, x0, (pz2 - draw_constant)/(pz2 - pz0)); my1 = convex_pt(y2, y0, (pz2 - draw_constant)/(pz2 - pz0)); mz1 = convex_pt(z2, z0, (pz2 - draw_constant)/(pz2 - pz0)); // 1-0 segment project_to_camera(mx0, my0, mz0, &mpx0, &mpy0, &mpz0) ; // 0-2 segment project_to_camera(mx1, my1, mz1, &mpx1, &mpy1, &mpz1) ; } else if(pz1 < draw_constant) { // pz0 >= draw_constant and pz2 >+ draw_constant fpx0 = px0 ; fpy0 = py0 ; fpz0 = pz0 ; fpx1 = px2 ; fpy1 = py2 ; fpz1 = pz2 ; mx0 = convex_pt(x0, x1, (pz0 - draw_constant)/(pz0 - pz1)); my0 = convex_pt(y0, y1, (pz0 - draw_constant)/(pz0 - pz1)); mz0 = convex_pt(z0, z1, (pz0 - draw_constant)/(pz0 - pz1)); mx1 = convex_pt(x2, x1, (pz2 - draw_constant)/(pz2 - pz1)); my1 = convex_pt(y2, y1, (pz2 - draw_constant)/(pz2 - pz1)); mz1 = convex_pt(z2, z1, (pz2 - draw_constant)/(pz2 - pz1)); // 0-1 segment project_to_camera(mx0, my0, mz0, &mpx0, &mpy0, &mpz0) ; // 1-2 segment project_to_camera(mx1, my1, mz1, &mpx1, &mpy1, &mpz1) ; } else /*if(pz2 < draw_constant)*/ { // pz1 >= draw_constant and pz0 >+ draw_constant fpx0 = px0 ; fpy0 = py0 ; fpz0 = pz0 ; fpx1 = px1 ; fpy1 = py1 ; fpz1 = pz1 ; mx0 = convex_pt(x0, x2, (pz0 - draw_constant)/(pz0 - pz2)); my0 = convex_pt(y0, y2, (pz0 - draw_constant)/(pz0 - pz2)); mz0 = convex_pt(z0, z2, (pz0 - draw_constant)/(pz0 - pz2)); mx1 = convex_pt(x1, x2, (pz1 - draw_constant)/(pz1 - pz2)); my1 = convex_pt(y1, y2, (pz1 - draw_constant)/(pz1 - pz2)); mz1 = convex_pt(z1, z2, (pz1 - draw_constant)/(pz1 - pz2)); // 0-2 segment project_to_camera(mx0, my0, mz0, &mpx0, &mpy0, &mpz0) ; // 1-2 segment project_to_camera(mx1, my1, mz1, &mpx1, &mpy1, &mpz1) ; } triangles_to_render[triangles_i][0] = to_pt_2d(1500.0 * (1.0 + (fpx0 / (1.5 * fpz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (fpy0 / (fpz0 * tan_fov))) / 2.0, getZbuffer(fpx0, fpy0, fpz0)); triangles_to_render[triangles_i][1] = to_pt_2d(1500.0 * (1.0 + (mpx0 / (1.5 * mpz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (mpy0 / (mpz0 * tan_fov))) / 2.0, getZbuffer(mpx0, mpy0, mpz0)); triangles_to_render[triangles_i][2] = to_pt_2d(1500.0 * (1.0 + (fpx1 / (1.5 * fpz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (fpy1 / (fpz1 * tan_fov))) / 2.0, getZbuffer(fpx1, fpy1, fpz1)); if(bbox_inside_cam(triangles_i)) { triangles_og_coords[triangles_i][0] = to_pt_2d(fpx0, fpy0, fpz0); triangles_og_coords[triangles_i][1] = to_pt_2d(mpx0, mpy0, mpz0); triangles_og_coords[triangles_i][2] = to_pt_2d(fpx1, fpy1, fpz1); reds[triangles_i] = red ; greens[triangles_i] = green ; blues[triangles_i] = blue ; triangles_i += 1; } //triangles_areas[triangles_i] = area_of_triangle(triangles_to_render[triangles_i]); triangles_to_render[triangles_i][0] = to_pt_2d(1500.0 * (1.0 + (mpx0 / (1.5 * mpz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (mpy0 / (mpz0 * tan_fov))) / 2.0, getZbuffer(mpx0, mpy0, mpz0)); triangles_to_render[triangles_i][1] = to_pt_2d(1500.0 * (1.0 + (mpx1 / (1.5 * mpz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (mpy1 / (mpz1 * tan_fov))) / 2.0, getZbuffer(mpx1, mpy1, mpz1)); triangles_to_render[triangles_i][2] = to_pt_2d(1500.0 * (1.0 + (fpx1 / (1.5 * fpz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (fpy1 / (fpz1 * tan_fov))) / 2.0, getZbuffer(fpx1, fpy1, fpz1)); if(bbox_inside_cam(triangles_i)) { triangles_og_coords[triangles_i][0] = to_pt_2d(mpx0, mpy0, mpz0); triangles_og_coords[triangles_i][1] = to_pt_2d(mpx1, mpy1, mpz1); triangles_og_coords[triangles_i][2] = to_pt_2d(fpx1, fpy1, fpz1); reds[triangles_i] = red ; greens[triangles_i] = green ; blues[triangles_i] = blue ; triangles_i += 1; } //triangles_areas[triangles_i+1] = area_of_triangle(triangles_to_render[triangles_i+1]); } else if((pz0 >= draw_constant) + (pz1 >= draw_constant) + (pz2 >= draw_constant) == 1) { if(pz0 >= draw_constant) { project_to_camera( convex_pt(x0, x1, (pz0 - draw_constant)/(pz0 - pz1)), convex_pt(y0, y1, (pz0 - draw_constant)/(pz0 - pz1)), convex_pt(z0, z1, (pz0 - draw_constant)/(pz0 - pz1)), &px1, &py1, &pz1); project_to_camera( convex_pt(x0, x2, (pz0 - draw_constant)/(pz0 - pz2)), convex_pt(y0, y2, (pz0 - draw_constant)/(pz0 - pz2)), convex_pt(z0, z2, (pz0 - draw_constant)/(pz0 - pz2)), &px2, &py2, &pz2); } else if(pz1 >= draw_constant) { project_to_camera( convex_pt(x1, x0, (pz1 - draw_constant)/(pz1 - pz0)), convex_pt(y1, y0, (pz1 - draw_constant)/(pz1 - pz0)), convex_pt(z1, z0, (pz1 - draw_constant)/(pz1 - pz0)), &px0, &py0, &pz0); project_to_camera( convex_pt(x1, x2, (pz1 - draw_constant)/(pz1 - pz2)), convex_pt(y1, y2, (pz1 - draw_constant)/(pz1 - pz2)), convex_pt(z1, z2, (pz1 - draw_constant)/(pz1 - pz2)), &px2, &py2, &pz2); } else if(pz2 >= draw_constant) { project_to_camera( convex_pt(x2, x0, (pz2 - draw_constant)/(pz2 - pz0)), convex_pt(y2, y0, (pz2 - draw_constant)/(pz2 - pz0)), convex_pt(z2, z0, (pz2 - draw_constant)/(pz2 - pz0)), &px0, &py0, &pz0); project_to_camera( convex_pt(x2, x1, (pz2 - draw_constant)/(pz2 - pz1)), convex_pt(y2, y1, (pz2 - draw_constant)/(pz2 - pz1)), convex_pt(z2, z1, (pz2 - draw_constant)/(pz2 - pz1)), &px1, &py1, &pz1); } triangles_to_render[triangles_i][0] = to_pt_2d(1500.0 * (1.0 + (px0 / (1.5 * pz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py0 / (pz0 * tan_fov))) / 2.0, getZbuffer(px0, py0, pz0)); triangles_to_render[triangles_i][1] = to_pt_2d(1500.0 * (1.0 + (px1 / (1.5 * pz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py1 / (pz1 * tan_fov))) / 2.0, getZbuffer(px1, py1, pz1)); triangles_to_render[triangles_i][2] = to_pt_2d(1500.0 * (1.0 + (px2 / (1.5 * pz2 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py2 / (pz2 * tan_fov))) / 2.0, getZbuffer(px2, py2, pz2)); if(bbox_inside_cam(triangles_i)) { triangles_og_coords[triangles_i][0] = to_pt_2d(px0, py0, pz0); triangles_og_coords[triangles_i][1] = to_pt_2d(px1, py1, pz1); triangles_og_coords[triangles_i][2] = to_pt_2d(px2, py2, pz2); //triangles_areas[triangles_i] = area_of_triangle(triangles_to_render[triangles_i]); reds[triangles_i] = red ; greens[triangles_i] = green ; blues[triangles_i] = blue ; triangles_i += 1; } } else { } } } void addTriangleRotated( 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); addTriangle(px0, py0, pz0, px1, py1, pz1, px2, py2, pz2, red, green, blue); } // -------------------------------------------------------------------------------------------------------------------------------- // void add_single(cube_0 c) { // x int leng = surfaceDrawOrder(camx, camy, camz, c); for(int sf0 = 0; sf0 < leng; sf0++) { int sf = drawOrder[sf0]; if(sf == 0 || sf == 1) { addTriangleRotated( 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 ); addTriangleRotated( 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) { addTriangleRotated( 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 ); addTriangleRotated( 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 addTriangleRotated( 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 ); addTriangleRotated( 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 add_triangles_cb(cube_0* arr, int len) { for(int k = 0; k < len; k++) { add_single(arr[k]); } } void add_triangles_tp(teleporter* arr, int len) { for(int k = 0; k < len; k++) { add_single(arr[k].hitbox); } } void add_triangles_ent(entity* arr, int len) { for(int k = 0; k < len; k++) { add_single(*(arr[k].pos)); } } void renderTriangleFull(SDL_Renderer* renderer, int k) { renderTriangleNoProject(renderer, triangles_to_render[k][0].x, triangles_to_render[k][0].y, triangles_to_render[k][0].z, triangles_to_render[k][1].x, triangles_to_render[k][1].y, triangles_to_render[k][1].z, triangles_to_render[k][2].x, triangles_to_render[k][2].y, triangles_to_render[k][2].z, reds[k], greens[k], blues[k], false ); } void remove_hidden(SDL_Renderer* renderer) { printf("%d --> ", triangles_i); for(int k = 0; k < triangles_i; k++) { int halt = 1 ; bool fst = false ; bool snd = false ; bool thd = false ; for(int l = 0; l < halt*triangles_i; l++) { if(l != k) { fst = fst || (is_hidden(renderer, triangles_to_render[k][0], triangles_og_coords[k][0], triangles_to_render[l], triangles_og_coords[l])); snd = snd || (is_hidden(renderer, triangles_to_render[k][1], triangles_og_coords[k][1], triangles_to_render[l], triangles_og_coords[l])); thd = thd || (is_hidden(renderer, triangles_to_render[k][2], triangles_og_coords[k][2], triangles_to_render[l], triangles_og_coords[l])); if(fst && snd && thd) { triangles_to_render[k][0] = triangles_to_render[triangles_i-1][0] ; triangles_to_render[k][1] = triangles_to_render[triangles_i-1][1] ; triangles_to_render[k][2] = triangles_to_render[triangles_i-1][2] ; reds[k] = reds[triangles_i-1]; greens[k] = greens[triangles_i-1]; blues[k] = blues[triangles_i-1]; //triangles_areas[k] = triangles_areas[triangles_i-1]; triangles_i -= 1; k -= 1; halt = 0; } } } } printf("%d\n", triangles_i); } void visit(int k, bool vflag) { if(visited_tri[k] != vflag) { visited_tri[k] = vflag ; for(int l = 0; l < triangles_i; l++) { if(l != k && visited_tri[l] != vflag) { if(is_in_front(triangles_to_render[k], triangles_og_coords[k], triangles_to_render[l], triangles_og_coords[l])) { visit(l, vflag); } } } triangles_order[visited_i] = k; visited_i += 1; } } void topological_sort() { bool vflag = !visited_tri[0]; for(int k = 0; k < triangles_i; k++) { visit(k, vflag); } } void drawCurrentRoom(SDL_Renderer* renderer) { triangles_i = 0; visited_i = 0; add_triangles_cb(current_room->map, current_room->map_size); add_triangles_tp(current_room->tps, current_room->tps_size); add_triangles_ent(current_room->ents, current_room->ent_len); topological_sort(); //remove_hidden(renderer); //topological_sort(); for(int k = 0; k < triangles_i; k++) { renderTriangleFull(renderer, triangles_order[k]); } /*for(int k = 0; k < triangles_i; k++) { drawNumberToRenderer(renderer, digits, (int)(3.3*(proj_pt_distance_to_camera(triangles_og_coords[k][0])+proj_pt_distance_to_camera(triangles_og_coords[k][1])+proj_pt_distance_to_camera(triangles_og_coords[k][2]))), (int)(0.33*(triangles_to_render[k][0].x+triangles_to_render[k][1].x+triangles_to_render[k][2].x)), (int)(0.33*(triangles_to_render[k][0].y+triangles_to_render[k][1].y+triangles_to_render[k][2].y)), 75/4, 105/4, 0 ); }*/ for(int k = 0; k < 0*triangles_i; k++) { for(int l = 0; l < 3; l++) { drawNumberToRenderer(renderer, digits, (int)(proj_pt_distance_to_camera(triangles_og_coords[k][l])), (int)(triangles_to_render[k][l].x), (int)(triangles_to_render[k][l].y), 75/5, 105/5, 0 ); } } } // -------------------------------------------------------------------------------------------------------------------------------- // void drawData(SDL_Renderer* renderer) { drawNumberToRenderer(renderer, digits, (int)camx, 10, 10, 75/2, 105/2, 0) ; 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, 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); }