added basic 3d rendering functions

This commit is contained in:
Alexandre 2024-12-30 14:48:19 +01:00
parent 01d87ab3b6
commit 8a6f109d8a
15 changed files with 375 additions and 114 deletions

7
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"files.associations": {
"ncurses.h": "c",
"stdio.h": "c",
"math.h": "c"
}
}

View File

@ -4,11 +4,10 @@ LFLAGS = -lSDL2 -lSDL2_image -lm -lncurses
all: bin/back
test: bin/back
bin/back
bin/back: obj/main.o obj/generation.o obj/display.o obj/base.o obj/hash.o
bin/back: obj/main.o obj/generation.o obj/display.o obj/move.o obj/base.o obj/hash.o
mkdir -p bin
$(CC) $(FLAGS) $^ $(LFLAGS) -o $@
@ -19,6 +18,7 @@ obj/%.o: src/%.c
obj/main.o: src/main.c
obj/generation.o: src/generation.c
obj/display.o: src/display.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.

BIN
obj/move.o Normal file

Binary file not shown.

View File

@ -83,10 +83,6 @@ int to_int(double n) {
return (int)n ;
}
double distance_pt(int x1, int x2, int y1, int y2) {
return sqrt(to_double(pw(x2 - x1, 2) + pw(y2 - y1, 2)));
}
int line_count(char* filename) {
FILE* ptr = fopen(filename, "r");
char c = 'd';
@ -182,84 +178,91 @@ bool str_equal(char* s1, char* s2) {
// ------------------------------------------------------------------------------------------------ //
void linked_add(linkedList* lst, int x, int y, char* flag) {
if(lst == NULL) {
fprintf(stderr, "ERROR : linked list has not been initialized\n");
exit(1);
} else if(lst->next == NULL) {
lst->next = malloc(sizeof(linkedList));
lst->next->coord = x + 16*y ;
lst->next->flag = flag ;
lst->next->next = NULL ;
cube_0 create_cube_0(double x, double y, double z, double w, double h, double d, int r, int g, int b) {
cube_0 cb ;
cb.red = r ;
cb.green = g ;
cb.blue = b ;
cb.x = x ;
cb.y = y ;
cb.z = z ;
cb.w = w ;
cb.h = h ;
cb.d = d ;
cb.hz_angle = 0.0 ;
cb.vt_angle = 0.0 ;
return cb ;
}
cube create_cube(double x, double y, double z, double w, double h, double d, int r, int g, int b) {
cube cb = malloc(sizeof(cube_0));
*cb = create_cube_0(x, y, z, w, d, h, r, g, b) ;
return cb;
}
void free_cube(cube c) {
free(c) ;
}
// ------------------------------------------------------------------------------------------------ //
double convex_pt(double a, double b, double theta) {
return (a+(b-a)*theta) ;
}
double distance_pt_pt_3d(double x0, double y0, double z0, double x1, double y1, double z1) {
return sqrt((x1 - x0)*(x1 - x0)+(y1 - y0)*(y1 - y0)+(z1 - z0)*(z1 - z0)) ;
}
double distance_pt_seg_3d(double x, double y, double z, double sx, double sy, double sz, double ex, double ey, double ez) {
double theta = -(
((ex - sx) * (sx - x) + (ey - sy) * (sy - y) + (ez - sz) * (sz - z)) /
((ex - sx) * (ex - sx) + (ey - sy) * (ey - sy) + (ez - sz) * (ez - sz))
);
if(theta >= 0.0 && theta <= 1.0) {
return (distance_pt_pt_3d(x, y, z, convex_pt(sx, ex, theta), convex_pt(sy, ey, theta), convex_pt(sz, ez, theta))) ;
} else if (theta < 0.0) {
return (distance_pt_pt_3d(x, y, z, sx, sy, sz)) ;
} else {
linked_add(lst->next, x, y, flag);
return (distance_pt_pt_3d(x, y, z, ex, ey, ez)) ;
}
}
void linked_removeCoord(linkedList* lst, int x, int y) {
if(lst != NULL) {
if(lst->coord == x + 16*y) {
linkedList* temp = lst->next ;
free(lst) ;
lst = temp ;
} else {
linked_removeCoord(lst->next, x, y);
}
double distance_pt_cube_axis(double coord, double begin, double end) {
if(coord < begin) {
return (begin-coord) ;
} else if(coord > end) {
return (coord-end) ;
} else {
return 0.0 ;
}
}
void linked_removeFlag(linkedList* lst, char* flag) {
if(lst != NULL) {
if(lst->flag == flag) {
linkedList* temp = lst->next ;
free(lst) ;
lst = temp ;
} else {
linked_removeFlag(lst->next, flag);
}
}
double distance_pt_cube_aligned_3d(double x0, double y0, double z0, double cx, double cy, double cz, double cw, double ch, double cd) {
return (distance_pt_cube_axis(x0, cx, cx+cw)+distance_pt_cube_axis(y0, cy, cy+ch)+distance_pt_cube_axis(z0, cz, cz+cd)) ;
}
void linked_change(linkedList* lst, int x, int y, char* flag) {
linked_removeCoord(lst, x, y);
linked_add(lst, x, y, flag);
double distance_pt_cube_0_3d(double x0, double y0, double z0, cube_0 c) {
// places the origin at the center of the cube
double x = x0 - (c.x + c.w/2.0) ;
double y = y0 - (c.y + c.h/2.0) ;
double z = z0 - (c.z + c.d/2.0) ;
// rotate the point : y then x
double xry = x*cos(c.hz_angle) + z*sin(c.hz_angle) ;
double yry = y ;
double zry = z*cos(c.hz_angle) - x*sin(c.hz_angle) ;
double xrx = xry ;
double yrx = yry*cos(c.vt_angle) - zry*sin(c.vt_angle) ;
double zrx = zry*cos(c.vt_angle) + yry*sin(c.vt_angle) ;
// now the cube and pt are aligned, and (0, 0, 0) is at the cube's (bary)center
return distance_pt_cube_aligned_3d(xrx, yrx, zrx, -c.w/2.0, -c.h/2.0, -c.d/2.0, c.w/2.0, c.h/2.0, c.d/2.0) ;
}
bool linked_mem(linkedList* lst, int x, int y, char** flag) {
if(lst == NULL) {
return false;
}
if(lst->coord == x + 16*y) {
*flag = lst->flag;
return true ;
}
return linked_mem(lst->next, x, y, flag);
}
linkedList* linked_copy(linkedList* src) {
linkedList* new = malloc(sizeof(linkedList)) ;
new->flag = "E" ;
new->coord = 0 ;
new->next = NULL ;
//printf("in\n");
linkedList* curSrc = src->next ;
//printf("out\n");
while(curSrc != NULL) {
//printf("cp\n");
linked_add(new, curSrc->coord%8, curSrc->coord/16, curSrc->flag);
curSrc = curSrc->next;
}
return new ;
}
void linkedPrint(linkedList* lst) {
if(lst != NULL) {
printf("[(%d, %d), %s] ", lst->coord%8, lst->coord/16, lst->flag);
linkedPrint(lst->next);
}
double distance_pt_cube_3d(double x0, double y0, double z0, cube cb) {
return distance_pt_cube_0_3d(x0, y0, z0, *cb) ;
}
// ------------------------------------------------------------------------------------------------ //

View File

@ -2,59 +2,40 @@
#define BACK_BASE_H
int ln_baseN(int n, int b);
int pw(int x, int n);
int abs(int n);
int min(int a, int b);
int max(int a, int b);
double absf(double n);
int convex_seg(int x1, int x2, double theta);
bool is_an_integer(char c);
double to_double(int n);
int to_int(double n);
double distance_pt(int x1, int x2, int y1, int y2);
int line_count(char* filename);
int str_to_int(char* s);
int get_integer(FILE* ptr);
int get_integer_plus_align(FILE* ptr, FILE* ptr2);
int count_char_in_line(FILE* ptr, char c);
void terminate_line(FILE* ptr);
bool str_equal(char* s1, char* s2);
void linked_add(linkedList* lst, int x, int y, char* flag);
cube_0 create_cube_0(double x, double y, double z, double w, double h, double d, int r, int g, int b);
cube create_cube(double x, double y, double z, double w, double h, double d, int r, int g, int b);
void free_cube(cube c);
double convex_pt(double a, double b, double theta);
double distance_pt_pt_3d(double x0, double y0, double z0, double x1, double y1, double z1);
double distance_pt_seg_3d(double x, double y, double z, double sx, double sy, double sz, double ex, double ey, double ez);
void linked_removeCoord(linkedList* lst, int x, int y);
void linked_removeFlag(linkedList* lst, char* flag);
void linked_change(linkedList* lst, int x, int y, char* flag);
bool linked_mem(linkedList* lst, int x, int y, char** flag);
linkedList* linked_copy(linkedList* src);
void linkedPrint(linkedList* lst);
double convex_pt(double a, double b, double theta);
double distance_pt_pt_3d(double x0, double y0, double z0, double x1, double y1, double z1) ;
double distance_pt_seg_3d(double x, double y, double z, double sx, double sy, double sz, double ex, double ey, double ez);
double distance_pt_cube_axis(double coord, double begin, double end);
double distance_pt_cube_aligned_3d(double x0, double y0, double z0, double cx, double cy, double cz, double cw, double ch, double cd);
double distance_pt_cube_0_3d(double x0, double y0, double z0, cube_0 c);
double distance_pt_cube_3d(double x0, double y0, double z0, cube cb);
void import_digits(SDL_Renderer* renderer);
void import_letters(SDL_Renderer* renderer);
void free_digits(imgs dgts);
#endif

View File

@ -14,6 +14,7 @@
#include "hash.h"
#include "structure.h"
#include "base.h"
#include "move.h"
#include "generation.h"
#include "display.h"
@ -42,21 +43,40 @@ void placeRectToRenderer(SDL_Renderer* renderer, int X, int Y, int W, int H, int
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(x1, x2, y1, y2);
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(x1, x2, y1, y2);
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);
@ -135,3 +155,90 @@ void drawStringToRenderer(SDL_Renderer* renderer, imgs data, char* s, int X, int
k += 1;
}
}
// ---------------------------------------------------------------------------------------------------------------------------------- //
// 3D stuff
void project_to_camera(double x0, double y0, double z0, double* rx, double* ry, double* rz) {
// align camera 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)
*rx = xry ;
*ry = yry*cos(rot_vt) - zry*sin(rot_vt) ;
*rz = zry*cos(rot_vt) + yry*sin(rot_vt) ;
}
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 >= 0.4 && epz >= 0.4) {
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 >= 0.4) {
double midx = convex_pt(ex, sx, (epz - 0.4)/(epz - spz)) ;
double midy = convex_pt(ey, sy, (epz - 0.4)/(epz - spz)) ;
double midz = convex_pt(ez, sz, (epz - 0.4)/(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 >= 0.4) {
double midx = convex_pt(sx, ex, (spz - 0.4)/(spz - epz)) ;
double midy = convex_pt(sy, ey, (spz - 0.4)/(spz - epz)) ;
double midz = convex_pt(sz, ez, (spz - 0.4)/(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 drawOutlineOfCube_0(SDL_Renderer* renderer, cube_0 c) {
SDL_SetRenderDrawColor(renderer, c.red, c.green, c.blue, 255) ;
// x = constant
draw_segment(renderer, c.x, c.y, c.z, c.x + c.w, c.y, c.z) ;
draw_segment(renderer, c.x, c.y + c.h, c.z, c.x + c.w, c.y + c.h, c.z) ;
draw_segment(renderer, c.x, c.y, c.z + c.d, c.x + c.w, c.y, c.z + c.d) ;
draw_segment(renderer, c.x, c.y + c.h, c.z + c.d, c.x + c.w, c.y + c.h, c.z + c.d) ;
// y = constant
draw_segment(renderer, c.x, c.y, c.z, c.x, c.y + c.h, c.z) ;
draw_segment(renderer, c.x + c.w, c.y, c.z, c.x + c.w, c.y + c.h, c.z) ;
draw_segment(renderer, c.x, c.y, c.z + c.d, c.x, c.y + c.h, c.z + c.d) ;
draw_segment(renderer, c.x + c.w, c.y, c.z + c.d, c.x + c.w, c.y + c.h, c.z + c.d) ;
// z = constant
draw_segment(renderer, c.x, c.y, c.z, c.x, c.y, c.z + c.d) ;
draw_segment(renderer, c.x + c.w, c.y, c.z, c.x + c.w, c.y, c.z + c.d) ;
draw_segment(renderer, c.x, c.y + c.h, c.z, c.x, c.y + c.h, c.z + c.d) ;
draw_segment(renderer, c.x + c.w, c.y + c.h, c.z, c.x + c.w, c.y + c.h, c.z + c.d) ;
}
// -------------------------------------------------------------------------------------------------------------------------------- //
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) ;
}

View File

@ -2,23 +2,27 @@
#define DISPLAY_H
void updateRenderer(SDL_Renderer* renderer);
void resetRenderer(SDL_Renderer* renderer);
void drawRectToRenderer(SDL_Renderer* renderer, SDL_Rect* rect, int R, int G, int B, int A);
void placeRectToRenderer(SDL_Renderer* renderer, int X, int Y, int W, int H, int R, int G, int B, int A);
void placeRectToRendererNoColor(SDL_Renderer* renderer, int X, int Y, int W, int H);
void drawLineWithThicc(SDL_Renderer* renderer, int width, int x1, int x2, int y1, int y2, int R, int G, int B, int A);
void drawLineWithThiccNoColor(SDL_Renderer* renderer, int width, int x1, int x2, int y1, int y2);
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);
void drawDigitToRenderer(SDL_Renderer* renderer, imgs data, int digit, int X, int Y, int W, int H);
void drawCharToRenderer(SDL_Renderer* renderer, imgs data, char c, int X, int Y, int W, int H);
void drawNumberToRenderer(SDL_Renderer* renderer, imgs data, int n, int X, int Y, int W, int H, int Woffset);
void drawStringToRenderer(SDL_Renderer* renderer, imgs data, char* s, int X, int Y, int W, int H);
void project_to_camera(double x0, double y0, double z0, double* rx, double* ry, double* rz);
void draw_segment(SDL_Renderer* renderer, double sx, double sy, double sz, double ex, double ey, double ez);
void drawOutlineOfCube_0(SDL_Renderer* renderer, cube_0 c);
void drawData(SDL_Renderer* renderer);
#endif

View File

@ -14,6 +14,7 @@
#include "hash.h"
#include "structure.h"
#include "base.h"
#include "move.h"
#include "display.h"
#include "generation.h"
@ -28,7 +29,7 @@ int main(int argc, char** argv) {
SDL_Window* win = SDL_CreateWindow("Game",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
1000, 1000, 0);
1500, 1000, 0);
Uint32 render_flags = SDL_RENDERER_ACCELERATED;
SDL_Renderer* rend = SDL_CreateRenderer(win, -1, render_flags);
@ -39,10 +40,26 @@ int main(int argc, char** argv) {
fprintf(stderr, "cannot initialize audio");
exit(1);
}
SDL_SetRelativeMouseMode(true) ;
/* -------------------------------------------------------- */
init_csts() ;
import_digits(rend) ;
import_letters(rend) ;
cube_0 cb = create_cube_0(1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 255, 255, 255) ;
while(true) {
resetRenderer(rend) ;
SDL_SetRenderDrawColor(rend, 255, 255, 255, 255) ;
playerActions() ;
drawData(rend) ;
drawOutlineOfCube_0(rend, cb) ;
//draw_segment(rend, 1.0, 1.0, 1.0, 10.0, 2.0, -1.0) ;
updateRenderer(rend) ;
usleep(1000000/60) ;
}
free_digits(digits) ;
/* -------------------------------------------------------- */

110
src/move.c Normal file
View File

@ -0,0 +1,110 @@
#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 "move.h"
// ---------------------------------------------------------------------------------------------------- //
double sensitivity = 0.3 ;
double fov = 90.0 ;
double speed = 1.0 ;
// ---------------------------------------------------------------------------------------------------- //
double camx ;
double camy ;
double camz ;
double rot_hz ;
double rot_vt ;
double tan_fov ;
bool has_changed ;
void init_csts() {
camx = 0.0 ;
camy = 0.0 ;
camz = 0.0 ;
rot_hz = 0.0 ;
rot_vt = 0.0 ;
tan_fov = tan((fov * 3.14159 / 180.0) / 2.0) ;
}
void playerActions() {
SDL_Event event;
while(SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
break;
case SDL_MOUSEMOTION:
has_changed = true ;
rot_hz -= sensitivity * event.motion.xrel / 100.0 ;
rot_vt -= sensitivity * event.motion.yrel / 100.0 ;
if(rot_hz >= 2*3.141592) {
rot_hz -= 2*3.141592 ;
} else if(rot_hz < 0.0) {
rot_hz += 2*3.141592 ;
}
if(rot_vt >= 2*3.141592) {
rot_vt -= 2*3.141592 ;
} else if(rot_vt < 0.0) {
rot_vt += 2*3.141592 ;
}
break;
case SDL_KEYDOWN:
has_changed = true ;
switch (event.key.keysym.sym) {
case SDLK_z:
camz += speed*cos(rot_hz);
camx -= speed*sin(rot_hz);
break;
case SDLK_q:
camx -= speed*cos(rot_hz);
camz -= speed*sin(rot_hz);
break;
case SDLK_s:
camz -= speed*cos(rot_hz);
camx += speed*sin(rot_hz);
break;
case SDLK_d:
camx += speed*cos(rot_hz);
camz += speed*sin(rot_hz);
break;
case SDLK_t:
fprintf(stderr, "Killed.\n") ;
exit(1) ;
break;
case SDLK_a:
rot_hz -= sensitivity ;
break;
case SDLK_e:
rot_hz += sensitivity ;
break;
case SDLK_p:
rot_vt -= sensitivity ;
break;
case SDLK_m:
rot_vt += sensitivity ;
break;
default:
break;
}
}
}
}

7
src/move.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef MOVE_H
#define MOVE_H
void init_csts();
void playerActions();
#endif

View File

@ -6,7 +6,32 @@ typedef struct imgs {
SDL_Texture** arr;
} imgs ;
struct cube_0 {
int red; int green; int blue ;
double x;
double y;
double z;
double w;
double h;
double d;
double hz_angle ;
double vt_angle ;
} ;
typedef struct cube_0 cube_0 ;
typedef cube_0* cube ;
extern imgs digits ;
extern imgs letters ;
extern double camx ;
extern double camy ;
extern double camz ;
extern double rot_hz ;
extern double rot_vt ;
extern double tan_fov ;
extern bool has_changed ;
#endif