This commit is contained in:
Alexandre 2025-01-18 17:57:47 +01:00
parent 16cf96d8ac
commit db60e9a707
18 changed files with 425 additions and 29 deletions

View File

@ -7,6 +7,7 @@
"display.h": "c",
"generation.h": "c",
"time.h": "c",
"limits": "c"
"limits": "c",
"sdl.h": "c"
}
}

View File

@ -7,7 +7,7 @@ all: bin/back
test: bin/back
bin/back
bin/back: obj/main.o obj/generation.o obj/display.o obj/entities.o obj/move.o obj/base.o obj/hash.o
bin/back: obj/main.o obj/generation.o obj/display.o obj/entities.o obj/triangles.o obj/move.o obj/base.o obj/hash.o
mkdir -p bin
$(CC) $(FLAGS) $^ $(LFLAGS) -o $@
@ -19,6 +19,7 @@ obj/main.o: src/main.c
obj/generation.o: src/generation.c
obj/display.o: src/display.c
obj/entities.o: src/entities.c
obj/triangles.o: src/triangles.c
obj/move.o: src/move.c
obj/base.o: src/base.c
obj/hash.o: src/hash.c

BIN
bin/back

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
obj/triangles.o Normal file

Binary file not shown.

View File

@ -297,6 +297,23 @@ double distance_pt_cube_3d(double x0, double y0, double z0, cube cb) {
return distance_pt_cube_0_3d(x0, y0, z0, *cb) ;
}
void project_to_camera(double x0, double y0, double z0, double* rx, double* ry, double* rz) {
// align pt to (0, 0, 0)
double x = x0 - camx ;
double y = y0 - camy ;
double z = z0 - camz ;
// rotate (y)
double xry = x*cos(rot_hz) + z*sin(rot_hz) ;
double yry = y ;
double zry = z*cos(rot_hz) - x*sin(rot_hz) ;
// rotate (x)
if(rx != NULL) {*rx = xry ;}
if(ry != NULL) {*ry = yry*cos(rot_vt) - zry*sin(rot_vt) ;}
if(rz != NULL) {*rz = zry*cos(rot_vt) + yry*sin(rot_vt) ;}
}
// ------------------------------------------------------------------------------------------------ //
void remove_entity(entity** arr, int* memlen, int* len, int index) {

View File

@ -48,6 +48,7 @@ void remove_entity(entity** arr, int* memlen, int* len, int index);
void add_entity(entity** arr, int* memlen, int* len, entity ent);
double distance_pt_cube_3d(double x0, double y0, double z0, cube cb);
void project_to_camera(double x0, double y0, double z0, double* rx, double* ry, double* rz);
void import_digits(SDL_Renderer* renderer);
void import_letters(SDL_Renderer* renderer);

View File

@ -14,6 +14,7 @@
#include "hash.h"
#include "structure.h"
#include "base.h"
#include "triangles.h"
#include "move.h"
#include "entities.h"
#include "generation.h"
@ -21,10 +22,11 @@
int* drawOrder;
double draw_constant = 0.4 ;
double draw_constant ;
void init_draworder() {
drawOrder = malloc(sizeof(int)*6) ;
draw_constant = 0.4 ;
}
void updateRenderer(SDL_Renderer* renderer) {
@ -168,25 +170,6 @@ 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 pt to (0, 0, 0)
double x = x0 - camx ;
double y = y0 - camy ;
double z = z0 - camz ;
// rotate (y)
double xry = x*cos(rot_hz) + z*sin(rot_hz) ;
double yry = y ;
double zry = z*cos(rot_hz) - x*sin(rot_hz) ;
// rotate (x)
if(rx != NULL) {*rx = xry ;}
if(ry != NULL) {*ry = yry*cos(rot_vt) - zry*sin(rot_vt) ;}
if(rz != NULL) {*rz = zry*cos(rot_vt) + yry*sin(rot_vt) ;}
}
// ---------------------------------------------------------------------------------------------------------------------------------- //
double pt_z_distance_to_camera(double x, double y, double z) {
double ret ;
project_to_camera(x, y, z, NULL, NULL, &ret) ;
@ -450,13 +433,6 @@ SDL_Vertex construct_vertex(double px, double py, int r, int g, int b) {
return vtx ;
}
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;
void renderTriangle(
SDL_Renderer* renderer,
double x0, double y0, double z0,
@ -732,6 +708,23 @@ void drawCurrentRoom(SDL_Renderer* renderer) {
insertionSort_tp(current_room->tps, current_room->tps_size);
insertionSort_ent(current_room->ents, current_room->ent_len);
for(int k1 = 0; k1 < current_room->map_size; k1++) {
current_room->map[k1].red = 188 ;
current_room->map[k1].green = 0 ;
current_room->map[k1].blue = 0 ;
}
for(int k1 = 0; k1 < current_room->map_size; k1++) {
for(int k2 = k1+1; k2 < current_room->map_size; k2++) {
if(cubeOverlap(current_room->map[k1], current_room->map[k2])) {
current_room->map[k1].red = 0 ;
current_room->map[k1].green = 188 ;
current_room->map[k2].red = 0 ;
current_room->map[k2].green = 188 ;
}
}
}
if(true || draw_type == 0) {
for(int k = 0; k < current_room->map_size; k++) {
drawFullCube(renderer, current_room->map[k]);

View File

@ -54,6 +54,7 @@ int main(int argc, char** argv) {
init_csts() ;
init_hashtbl() ;
init_draworder() ;
trInit();
parse_rooms(3);
import_digits(rend) ;
import_letters(rend) ;

View File

@ -6,6 +6,12 @@ typedef struct imgs {
SDL_Texture** arr;
} imgs ;
typedef struct pt_2d {
double x;
double y;
double z;
} pt_2d ;
struct cube_0 {
int red; int green; int blue ;
double x;
@ -107,4 +113,14 @@ extern int coins ;
extern int draw_type ;
extern double draw_constant ;
extern double px0; extern double py0; extern double pz0;
extern double px1; extern double py1; extern double pz1;
extern double px2; extern double py2; extern double pz2;
extern double fpx0; extern double fpy0; extern double fpz0;
extern double fpx1; extern double fpy1; extern double fpz1;
extern double mpx0; extern double mpy0; extern double mpz0;
extern double mpx1; extern double mpy1; extern double mpz1;
#endif

346
src/triangles.c Normal file
View File

@ -0,0 +1,346 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <ncurses.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "hash.h"
#include "structure.h"
#include "base.h"
#include "triangles.h"
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;
int errno = 0;
pt_2d* triangle_1 ;
pt_2d* triangle_2 ;
pt_2d* cube_t1 ;
pt_2d* cube_t2 ;
void trInit() {
triangle_1 = malloc(sizeof(pt_2d)*3);
triangle_2 = malloc(sizeof(pt_2d)*3);
cube_t1 = malloc(sizeof(pt_2d)*6);
cube_t2 = malloc(sizeof(pt_2d)*6);
}
double det2D(pt_2d* p1, pt_2d* p2, pt_2d* p3) {
return p1->x * (p2->y - p3->y)
+ p2->x * (p3->y - p1->y)
+ p3->x * (p1->y - p2->y);
}
void checkTriWinding(pt_2d * p1, pt_2d * p2, pt_2d * p3, bool allowReversed) {
double detTri = det2D(p1, p2, p3);
if (detTri < 0.0) {
if (allowReversed) {
double t = p3->x;
p3->x = p2->x;
p2->x = t;
t = p3->y;
p3->y = p2->y;
p2->y = t;
} else {
errno = 1;
}
}
}
bool boundaryCollideChk(pt_2d *p1, pt_2d *p2, pt_2d *p3, double eps) {
return det2D(p1, p2, p3) < eps;
}
bool boundaryDoesntCollideChk(pt_2d *p1, pt_2d *p2, pt_2d *p3, double eps) {
return det2D(p1, p2, p3) <= eps;
}
bool triTri2D(pt_2d* t1, pt_2d* t2, double eps, bool allowReversed, bool onBoundary) {
bool(*chkEdge)(pt_2d*, pt_2d*, pt_2d*, double);
int i;
errno = 0;
// Triangles must be expressed anti-clockwise
checkTriWinding(&t1[0], &t1[1], &t1[2], allowReversed);
if (errno != 0) {
return false;
}
checkTriWinding(&t2[0], &t2[1], &t2[2], allowReversed);
if (errno != 0) {
return false;
}
if (onBoundary) {
// pt_2ds on the boundary are considered as colliding
chkEdge = boundaryCollideChk;
} else {
// pt_2ds on the boundary are not considered as colliding
chkEdge = boundaryDoesntCollideChk;
}
//For edge E of trangle 1,
for (i = 0; i < 3; ++i) {
int j = (i + 1) % 3;
//Check all points of trangle 2 lay on the external side of the edge E. If
//they do, the triangles do not collide.
if (chkEdge(&t1[i], &t1[j], &t2[0], eps) &&
chkEdge(&t1[i], &t1[j], &t2[1], eps) &&
chkEdge(&t1[i], &t1[j], &t2[2], eps)) {
return false;
}
}
//For edge E of trangle 2,
for (i = 0; i < 3; i++) {
int j = (i + 1) % 3;
//Check all points of trangle 1 lay on the external side of the edge E. If
//they do, the triangles do not collide.
if (chkEdge(&t2[i], &t2[j], &t1[0], eps) &&
chkEdge(&t2[i], &t2[j], &t1[1], eps) &&
chkEdge(&t2[i], &t2[j], &t1[2], eps))
return false;
}
//The triangles collide
return true;
}
bool triangleIntersection(pt_2d* tri1, pt_2d* tri2) {
return triTri2D(tri1, tri2, 0.0, false, true);
}
bool triangleIntersectionDec(pt_2d t1_1, pt_2d t1_2, pt_2d t1_3, pt_2d t2_1, pt_2d t2_2, pt_2d t2_3) {
triangle_1[0] = t1_1;
triangle_1[1] = t1_2;
triangle_1[2] = t1_3;
triangle_2[0] = t2_1;
triangle_2[1] = t2_2;
triangle_2[2] = t2_3;
return triangleIntersection(triangle_1, triangle_2);
}
bool multipleTrianglesIntersection(pt_2d* tri1, int len1, pt_2d* tri2, int len2) {
for(int k1 = 0; k1 < len1; k1+=3) {
for(int k2 = 0; k2 < len2; k2+=3) {
if(triangleIntersection(&tri1[k1], &tri2[k2])) {
return true;
}
}
}
return false ;
}
pt_2d to_fpoint(double x0, double y0, double z0) {
pt_2d res;
res.x = x0;
res.y = y0;
res.z = z0;
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, pz0);
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, pz1);
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, pz2);
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, fpz0);
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, mpz0);
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, fpz1);
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, mpz0);
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, mpz1);
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, fpz1);
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, pz0);
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, pz1);
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, pz2);
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
if(trig == 0) {
return returnTriangle(
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,
ret
);
} else {
return returnTriangle(
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,
ret
);
}
} else { // z
if(trig == 0) {
return returnTriangle(
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),
ret
);
} else {
return returnTriangle(
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),
ret
);
}
}
}
bool cubeOverlap(cube_0 c1, cube_0 c2) {
int len1 = 0;
int len2 = 0;
for(int i1 = 0; i1 < 6; i1++) {
for(int i2 = i1+1; i2 < 6; i2++) {
for(int n = 0; n < 4; n++) {
len1 = fillPolygon(i1, c1, n%2, cube_t1);
len2 = fillPolygon(i2, c2, n/2, cube_t2);
if(multipleTrianglesIntersection(cube_t1, len1, cube_t2, len2)) {
return true;
}
}
}
}
return false;
}

20
src/triangles.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef TRIANGLES_H
#define TRIANGLES_H
void trInit();
double det2D(pt_2d * p1, pt_2d * p2, pt_2d * p3) ;
void checkTriWinding(pt_2d * p1, pt_2d * p2, pt_2d * p3, bool allowReversed) ;
bool boundaryCollideChk(pt_2d *p1, pt_2d *p2, pt_2d *p3, double eps) ;
bool boundaryDoesntCollideChk(pt_2d *p1, pt_2d *p2, pt_2d *p3, double eps) ;
bool triTri2D(pt_2d* t1, pt_2d* t2, double eps, bool allowReversed, bool onBoundary) ;
bool triangleIntersection(pt_2d* tri1, pt_2d* tri2);
bool triangleIntersectionDec(pt_2d t1_1, pt_2d t1_2, pt_2d t1_3, pt_2d t2_1, pt_2d t2_2, pt_2d t2_3);
int returnTriangle(double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, pt_2d* retarr);
int fillPolygon(int sf, cube_0 c, int trig, pt_2d* ret);
bool cubeOverlap(cube_0 c1, cube_0 c2);
#endif