diff --git a/bin/back b/bin/back index 118e36d..0927327 100755 Binary files a/bin/back and b/bin/back differ diff --git a/obj/base.o b/obj/base.o index dd1cc78..b7571fb 100644 Binary files a/obj/base.o and b/obj/base.o differ diff --git a/obj/display.o b/obj/display.o index 54efa0d..6be9d23 100644 Binary files a/obj/display.o and b/obj/display.o differ diff --git a/src/base.c b/src/base.c index 3792cc9..8d7d303 100644 --- a/src/base.c +++ b/src/base.c @@ -297,6 +297,65 @@ double distance_pt_cube_3d(double x0, double y0, double z0, cube cb) { return distance_pt_cube_0_3d(x0, y0, z0, *cb) ; } +// ---------------- // + +double distance_seg_seg_1d(double s0, double e0, double s1, double e1) { + double theta_s0 = -(((e1 - s1) * (s1 - s0)) / ((e1 - s1) * (e1 - s1))); + double theta_e0 = -(((e1 - s1) * (s1 - e0)) / ((e1 - s1) * (e1 - s1))); + if( + (theta_s0 >= 0.0 && theta_s0 <= 1.0) || // s0 is in [s1, e1] + (theta_e0 >= 0 && theta_e0 <= 1.0) || // s1 is in [s1, e1] + (theta_s0 < 0.0 && theta_e0 > 1.0) || // inclusion + (theta_e0 < 0.0 && theta_s0 > 1.0)) // inclusion + { + return 0.0; + } else { + double dist0 = mind(absf(theta_s0), absf(1.0 - theta_s0)) ; + double dist1 = mind(absf(theta_e0), absf(1.0 - theta_e0)) ; // get the closest theta to [0, 1] + return mind(dist1, dist0)*absf(e1 - s1); + } +} + +double distance_seg_seg_2d( + double s0x, double s0y, + double e0x, double e0y, + double s1x, double s1y, + double e1x, double e1y +) { + // basically ||.||_1 + return ( + distance_seg_seg_1d(s0x, e0x, s1x, e1x) + + distance_seg_seg_1d(s0y, e0y, s1y, e1y) + ); +} + +double distance_seg_seg_3d( + double s0x, double s0y, double s0z, + double e0x, double e0y, double e0z, + double s1x, double s1y, double s1z, + double e1x, double e1y, double e1z +) { + // same + return ( + distance_seg_seg_1d(s0x, e0x, s1x, e1x) + + distance_seg_seg_1d(s0y, e0y, s1y, e1y) + + distance_seg_seg_1d(s0z, e0z, s1z, e1z) + ); +} + +double distance_poly_poly_2d(pt_2d* t1, int len_1, pt_2d* t2, int len_2) { + double res = 10000.0 ; + for(int k1 = 0; k1 < len_1; k1++) { + for(int k2 = 0; k2 < len_1; k2++) { + res = mind(res, distance_seg_seg_2d( + t1[k1].x, t1[k1].y, t1[(k1+1)%len_1].x, t1[(k1+1)%len_1].y, + t2[k2].x, t2[k2].y, t2[(k2+1)%len_2].x, t2[(k2+1)%len_2].y + )); + } + } + return res; +} + // ------------------------------------------------------------------------------------------------ // void remove_entity(entity** arr, int* memlen, int* len, int index) { diff --git a/src/base.h b/src/base.h index d541b92..10a4703 100644 --- a/src/base.h +++ b/src/base.h @@ -44,6 +44,21 @@ double distance_pt_cube_axis_max(double coord, double begin, double end); double distance_pt_cube_aligned_3d_max(double x0, double y0, double z0, double cx, double cy, double cz, double cw, double ch, double cd); double distance_pt_cube_0_3d_max(double x0, double y0, double z0, cube_0 c); +double distance_seg_seg_1d(double s0, double e0, double s1, double e1); +double distance_seg_seg_2d( + double s0x, double s0y, + double e0x, double e0y, + double s1x, double s1y, + double e1x, double e1y +); +double distance_seg_seg_3d( + double s0x, double s0y, double s0z, + double e0x, double e0y, double e0z, + double s1x, double s1y, double s1z, + double e1x, double e1y, double e1z +); +double distance_poly_poly_2d(pt_2d* t1, int len_1, pt_2d* t2, int len_2); + void remove_entity(entity** arr, int* memlen, int* len, int index); void add_entity(entity** arr, int* memlen, int* len, entity ent); diff --git a/src/display.c b/src/display.c index 9a5bbc3..a7d6d99 100644 --- a/src/display.c +++ b/src/display.c @@ -20,11 +20,17 @@ #include "display.h" int* drawOrder; +int* drawOrder2; +pt_2d* tri1 ; +pt_2d* tri2 ; double draw_constant = 0.4 ; void init_draworder() { drawOrder = malloc(sizeof(int)*6) ; + drawOrder2 = malloc(sizeof(int)*6) ; + tri1 = malloc(sizeof(pt_2d)*6); + tri2 = malloc(sizeof(pt_2d)*6); } void updateRenderer(SDL_Renderer* renderer) { @@ -437,6 +443,57 @@ int surfaceDrawOrder(double x0, double y0, double z0, cube_0 cb) { } } +int surfaceDrawOrder2(double x0, double y0, double z0, cube_0 cb) { + // returns the number of surfaces that should be drawn, as well as filling drawOrder2 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) { + drawOrder2[id] = 0 ; + id += 1 ; + } else if(xrx < -cb.w/2.0) { + drawOrder2[id] = 1 ; + id += 1 ; + } + if(yrx > cb.h/2.0) { + drawOrder2[id] = 2 ; + id += 1 ; + } else if(yrx < -cb.h/2.0) { + drawOrder2[id] = 3 ; + id += 1 ; + } + if(zrx > cb.d/2.0) { + drawOrder2[id] = 4 ; + id += 1 ; + } else if(zrx < -cb.d/2.0) { + drawOrder2[id] = 5 ; + id += 1 ; + } + if(id == 0) { // inside the cube + for(int k = 0; k < 6; k++) { + drawOrder2[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 ; @@ -581,6 +638,196 @@ void renderTriangle( } } +pt_2d to_fpoint(double x0, double y0) { + pt_2d res; + res.x = x0; + res.y = y0; + return res; +} + +int returnTriangle( + double x0, double y0, double z0, + double x1, double y1, double z1, + double x2, double y2, double z2, + pt_2d* retarr +) { + 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 >= draw_constant && pz1 >= draw_constant && pz2 >= draw_constant) { + retarr[0] = to_fpoint(1500.0 * (1.0 + (px0 / (1.5 * pz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py0 / (pz0 * tan_fov))) / 2.0); + retarr[1] = to_fpoint(1500.0 * (1.0 + (px1 / (1.5 * pz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py1 / (pz1 * tan_fov))) / 2.0); + retarr[2] = to_fpoint(1500.0 * (1.0 + (px2 / (1.5 * pz2 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py2 / (pz2 * tan_fov))) / 2.0); + return 3; + } 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 ; + // 1-0 segment + 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)), + &mpx0, &mpy0, &mpz0) ; + + // 0-2 segment + 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)), + &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 ; + // 0-1 segment + 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)), + &mpx0, &mpy0, &mpz0) ; + + // 1-2 segment + 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)), + &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 ; + // 0-2 segment + 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)), + &mpx0, &mpy0, &mpz0) ; + + // 1-2 segment + 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)), + &mpx1, &mpy1, &mpz1) ; + } + + retarr[0] = to_fpoint(1500.0 * (1.0 + (fpx0 / (1.5 * fpz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (fpy0 / (fpz0 * tan_fov))) / 2.0); + retarr[1] = to_fpoint(1500.0 * (1.0 + (mpx0 / (1.5 * mpz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (mpy0 / (mpz0 * tan_fov))) / 2.0); + retarr[2] = to_fpoint(1500.0 * (1.0 + (fpx1 / (1.5 * fpz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (fpy1 / (fpz1 * tan_fov))) / 2.0); + retarr[3] = to_fpoint(1500.0 * (1.0 + (mpx0 / (1.5 * mpz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (mpy0 / (mpz0 * tan_fov))) / 2.0); + retarr[4] = to_fpoint(1500.0 * (1.0 + (mpx1 / (1.5 * mpz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (mpy1 / (mpz1 * tan_fov))) / 2.0); + retarr[5] = to_fpoint(1500.0 * (1.0 + (fpx1 / (1.5 * fpz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (fpy1 / (fpz1 * tan_fov))) / 2.0); + return 6; + } 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); + } + + retarr[0] = to_fpoint(1500.0 * (1.0 + (px0 / (1.5 * pz0 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py0 / (pz0 * tan_fov))) / 2.0); + retarr[1] = to_fpoint(1500.0 * (1.0 + (px1 / (1.5 * pz1 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py1 / (pz1 * tan_fov))) / 2.0); + retarr[2] = to_fpoint(1500.0 * (1.0 + (px2 / (1.5 * pz2 * tan_fov))) / 2.0, 1000.0 * (1.0 + (py2 / (pz2 * tan_fov))) / 2.0); + return 3; + } else { + return 0; + } +} + +int fillPolygon(int sf, cube_0 c, int trig, pt_2d* ret) { + // trig is either 0 or 1 + // returns the length of the result + if(sf == 0 || sf == 1) { // x + if(trig == 0) { + return returnTriangle( + 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, + ret + ); + } else { + return returnTriangle( + 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, + ret + ); + } + }/* 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 + ); + }*/ + return 0; +} + +double is_overlapping(cube_0 c1, cube_0 c2) { + // 0 if no overlap >0 if c1 is in front of c2, <0 if c2 is in front of c1 + int sfToDraw1 = surfaceDrawOrder(camx, camy, camz, c1); + int sfToDraw2 = surfaceDrawOrder2(camx, camy, camz, c2); + for(int k1 = 0; k1 < sfToDraw1; k1 ++) { + for(int k2 = 0; k2 < sfToDraw2; k2 ++) { + if(false/*isCollidingSfOfCube(drawOrder[k1], c1, drawOrder2[k2], c2)*/) { + return 1.0; + } + } + } + return 0.0; +} + void renderTriangleRotated( SDL_Renderer* renderer, double x0, double y0, double z0, diff --git a/src/structure.h b/src/structure.h index 20e7b6c..87dfb55 100644 --- a/src/structure.h +++ b/src/structure.h @@ -6,6 +6,11 @@ typedef struct imgs { SDL_Texture** arr; } imgs ; +typedef struct pt_2d { + double x; + double y; +} pt_2d ; + struct cube_0 { int red; int green; int blue ; double x; @@ -107,4 +112,7 @@ extern int coins ; extern int draw_type ; +extern pt_2d* tri1 ; +extern pt_2d* tri2 ; + #endif \ No newline at end of file