From 0c3f829c94d28264fcb6c72dc36e6f35ea6d836a Mon Sep 17 00:00:00 2001 From: H3XploR Date: Thu, 13 Feb 2025 20:18:32 +0100 Subject: [PATCH] NEW RAYTRACER --- calcul_de_vecteur.c | 59 ++++ miniRT.h | 89 ++++++ raytracer_formatted.c | 710 ++++++++++++++++++++++++++++++++++++++++++ tags | 121 +++++++ 4 files changed, 979 insertions(+) create mode 100644 calcul_de_vecteur.c create mode 100644 miniRT.h create mode 100644 raytracer_formatted.c create mode 100644 tags diff --git a/calcul_de_vecteur.c b/calcul_de_vecteur.c new file mode 100644 index 0000000..6f5128b --- /dev/null +++ b/calcul_de_vecteur.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* calcul_de_vecteur.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: yantoine +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/13 20:15:13 by yantoine #+# #+# */ +/* Updated: 2025/02/13 20:15:46 by yantoine ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "miniRT.h" + +// ----- Opérations sur les vecteurs + +t_vec3 vec3_add(t_vec3 a, t_vec3 b) +{ + return ((t_vec3){a.x + b.x, a.y + b.y, a.z + b.z}); +} + +t_vec3 vec3_sub(t_vec3 a, t_vec3 b) +{ + return ((t_vec3){a.x - b.x, a.y - b.y, a.z - b.z}); +} + +t_vec3 vec3_scale(t_vec3 a, float s) +{ + return ((t_vec3){a.x * s, a.y * s, a.z * s}); +} + +float vec3_dot(t_vec3 a, t_vec3 b) +{ + return (a.x * b.x + a.y * b.y + a.z * b.z); +} + +t_vec3 vec3_cross(t_vec3 a, t_vec3 b) +{ + return ((t_vec3){a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y + - a.y * b.x}); +} + +float vec3_length(t_vec3 a) +{ + return (sqrtf(vec3_dot(a, a))); +} + +t_vec3 vec3_normalize(t_vec3 a) +{ + float len; + + len = vec3_length(a); + return ((len > 0) ? vec3_scale(a, 1.0f / len) : a); +} + +t_vec3 vec3_mul(t_vec3 a, t_vec3 b) +{ + return ((t_vec3){a.x * b.x, a.y * b.y, a.z * b.z}); +} diff --git a/miniRT.h b/miniRT.h new file mode 100644 index 0000000..dece330 --- /dev/null +++ b/miniRT.h @@ -0,0 +1,89 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* miniRT.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: yantoine +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/13 20:02:36 by yantoine #+# #+# */ +/* Updated: 2025/02/13 20:16:50 by yantoine ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MINIRT_H +# define MINIRT_H + +# include +# include +# include +# include +# include +# include + +// ----- Taille ecran ---- +# define WIDTH 320 +# define HEIGHT 240 + +// ----- Tableaux de la scène ----- +# define MAX_SPHERES 128 +# define MAX_PLANES 128 +# define MAX_CYLINDERS 128 +# define MAX_LIGHTS 16 + +// ----- Structures +typedef struct s_vec3 +{ + float x; + float y; + float z; +} t_vec3; + +// ----- Ray ----- +typedef struct s_vec3 +{ + t_vec3 origin; + t_vec3 dir; +} t_ray; + +// ----- Objets de la scène ----- +typedef struct s_vec3 +{ + t_vec3 center; + float radius; + t_vec3 color; +} t_sphere; + +typedef struct s_vec3 +{ + t_vec3 point; + t_vec3 normal; + t_vec3 color; +} t_plane; + +typedef struct s_vec3 +{ + t_vec3 center; + t_vec3 axis;// Axe normalisé + float radius;// Demi-diamètre + float height; + t_vec3 color; +} t_cylinder; + +typedef struct s_vec3 +{ + t_vec3 pos; + float brightness; + t_vec3 color; +} t_light; + + +// Calcul de vecteur +t_vec3 vec3_add(t_vec3 a, t_vec3 b); +t_vec3 vec3_sub(t_vec3 a, t_vec3 b); +t_vec3 vec3_scale(t_vec3 a, float s); +float vec3_dot(t_vec3 a, t_vec3 b); +t_vec3 vec3_cross(t_vec3 a, t_vec3 b); +float vec3_length(t_vec3 a); +t_vec3 vec3_normalize(t_vec3 a); +t_vec3 vec3_mul(t_vec3 a, t_vec3 b); +#endif diff --git a/raytracer_formatted.c b/raytracer_formatted.c new file mode 100644 index 0000000..f554356 --- /dev/null +++ b/raytracer_formatted.c @@ -0,0 +1,710 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* raytracer_formatted.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: yantoine +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/02/13 19:56:17 by yantoine #+# #+# */ +/* Updated: 2025/02/13 20:16:00 by yantoine ### ########.fr */ +/* */ +/* ************************************************************************** */ + +/* + *Raytracer interactif en un seul fichier C avec lecture d'un fichier de configuration (.rt) + * + *Compilation (exemple sous Linux) : + * gcc raytracer.c -lSDL2 -lm -O2 -o raytracer + * + *Utilisation : + * ./raytracer config.rt + *Si aucun fichier n'est passé en argument, une scène par défaut est utilisée. + */ + +Sphere spheres[MAX_SPHERES]; +int numSpheres = 0; + +Plane planes[MAX_PLANES]; +int numPlanes = 0; + +Cylinder cylinders[MAX_CYLINDERS]; +int numCylinders = 0; + +Light lights[MAX_LIGHTS]; +int numLights = 0; + +// Ambient et caméra +float ambient_ratio = 0.1f; +t_vec3 ambient_color = {0.1f, 0.1f, 0.1f}; + +t_vec3 camPos = {0.0f, 0.0f, 0.0f}; +t_vec3 camDir = {0.0f, 0.0f, -1.0f}; +float fov = 90.0f; +float yaw = 0.0f, pitch = 0.0f; // en radians + +// ----- Parsing du fichier de configuration ----- +void load_config(const char *filename) +{ + FILE *fp; + char line[256]; + float ratio; + + fp = fopen(filename, "r"); + if (!fp) + { + fprintf(stderr, "Erreur : impossible d'ouvrir %s\n", filename); + return ; + } + while (fgets(line, sizeof(line), fp)) + { + // Ignore les lignes vides ou commençant par # + if (line[0] == '\n' || line[0] == '#') + continue ; + // Ambient lighting: A ratio R,G,B + if (line[0] == 'A') + { + int r, g, b; + if (sscanf(line, "A %f %d,%d,%d", &ratio, &r, &g, &b) == 4) + { + ambient_ratio = ratio; + ambient_color = (t_vec3){r / 255.0f, g / 255.0f, b / 255.0f}; + printf("Ambiance : ratio=%.2f, color=(%d,%d,%d)\n", ratio, r, g, + b); + } + } + // Camera: C pos_x,pos_y,pos_z norm_x,norm_y,norm_z FOV + else if (line[0] == 'C') + { + float px, py, pz, nx, ny, nz, f; + if (sscanf(line, "C %f,%f,%f %f,%f,%f %f", &px, &py, &pz, &nx, &ny, + &nz, &f) == 7) + { + camPos = (t_vec3){px, py, pz}; + camDir = vec3_normalize((t_vec3){nx, ny, nz}); + fov = f; + yaw = atan2f(camDir.x, -camDir.z); + pitch = asinf(camDir.y); + printf("Camera : pos=(%.2f,%.2f,%.2f), dir=(%.2f,%.2f,%.2f), + fov=%.2f\n", px, py, pz, nx, ny, nz, f); + } + } + // Light: L pos_x,pos_y,pos_z brightness R,G,B + else if (line[0] == 'L') + { + float lx, ly, lz, bright; + int r, g, b; + if (sscanf(line, "L %f,%f,%f %f %d,%d,%d", &lx, &ly, &lz, &bright, + &r, &g, &b) == 7) + { + if (numLights < MAX_LIGHTS) + { + lights[numLights].pos = (t_vec3){lx, ly, lz}; + lights[numLights].brightness = bright; + lights[numLights].color = (t_vec3){r / 255.0f, g / 255.0f, b + / 255.0f}; + numLights++; + printf("Light : pos=(%.2f,%.2f,%.2f), bright=%.2f, + color=(%d,%d,%d)\n", lx, ly, lz, bright, r, g, b); + } + } + } + // Sphere: sp pos_x,pos_y,pos_z diameter R,G,B + else if (strncmp(line, "sp", 2) == 0) + { + float cx, cy, cz, diam; + int r, g, b; + if (sscanf(line, "sp %f,%f,%f %f %d,%d,%d", &cx, &cy, &cz, &diam, + &r, &g, &b) == 7) + { + if (numSpheres < MAX_SPHERES) + { + spheres[numSpheres].center = (t_vec3){cx, cy, cz}; + spheres[numSpheres].radius = diam / 2.0f; + spheres[numSpheres].color = (t_vec3){r / 255.0f, g / 255.0f, + b / 255.0f}; + numSpheres++; + printf("Sphere : center=(%.2f,%.2f,%.2f), diam=%.2f, + color=(%d,%d,%d)\n", cx, cy, cz, diam, r, g, b); + } + } + } + // Plane: pl pos_x,pos_y,pos_z norm_x,norm_y,norm_z R,G,B + else if (strncmp(line, "pl", 2) == 0) + { + float px, py, pz, nx, ny, nz; + int r, g, b; + // Correction : nous attendons 9 éléments (3 + 3 + 3) + if (sscanf(line, "pl %f,%f,%f %f,%f,%f %d,%d,%d", &px, &py, &pz, + &nx, &ny, &nz, &r, &g, &b) == 9) + { + if (numPlanes < MAX_PLANES) + { + planes[numPlanes].point = (t_vec3){px, py, pz}; + planes[numPlanes].normal = vec3_normalize((t_vec3){nx, ny, + nz}); + planes[numPlanes].color = (t_vec3){r / 255.0f, g / 255.0f, b + / 255.0f}; + numPlanes++; + printf("Plane : point=(%.2f,%.2f,%.2f), + normal=(%.2f,%.2f,%.2f), color=(%d,%d,%d)\n", px, py, + pz, nx, ny, nz, r, g, b); + } + } + } + // Cylinder: cy pos_x,pos_y,pos_z axis_x,axis_y,axis_z diameter height R,G,B + else if (strncmp(line, "cy", 2) == 0) + { + float cx, cy, cz, ax, ay, az, diam, height; + int r, g, b; + // Correction : nous attendons 11 éléments (3 + 3 + 1 + 1 + 3) + if (sscanf(line, "cy %f,%f,%f %f,%f,%f %f %f %d,%d,%d", &cx, &cy, + &cz, &ax, &ay, &az, &diam, &height, &r, &g, &b) == 11) + { + if (numCylinders < MAX_CYLINDERS) + { + cylinders[numCylinders].center = (t_vec3){cx, cy, cz}; + cylinders[numCylinders].axis = vec3_normalize((t_vec3){ax, + ay, az}); + cylinders[numCylinders].radius = diam / 2.0f; + cylinders[numCylinders].height = height; + cylinders[numCylinders].color = (t_vec3){r / 255.0f, g + / 255.0f, b / 255.0f}; + numCylinders++; + printf("Cylinder : center=(%.2f,%.2f,%.2f), + axis=(%.2f,%.2f,%.2f), diam=%.2f, height=%.2f, + color=(%d,%d,%d)\n", cx, cy, cz, ax, ay, az, diam, + height, r, g, b); + } + } + } + } + fclose(fp); +} + +// ----- Fonctions d'intersection ----- +float intersectSphere(Ray ray, Sphere s, t_vec3 *hitNormal) +{ + t_vec3 oc; + float a; + float b; + float c; + float disc; + float sqrtDisc; + float t0; + float t1; + float t; + t_vec3 hitPoint; + + oc = vec3_sub(ray.origin, s.center); + a = vec3_dot(ray.dir, ray.dir); + b = 2.0f * vec3_dot(oc, ray.dir); + c = vec3_dot(oc, oc) - s.radius * s.radius; + disc = b * b - 4 * a * c; + if (disc < 0) + return (-1); + sqrtDisc = sqrtf(disc); + t0 = (-b - sqrtDisc) / (2 * a); + t1 = (-b + sqrtDisc) / (2 * a); + t = (t0 > 1e-3f) ? t0 : t1; + if (t < 1e-3f) + return (-1); + hitPoint = vec3_add(ray.origin, vec3_scale(ray.dir, t)); + *hitNormal = vec3_normalize(vec3_sub(hitPoint, s.center)); + return (t); +} + +float intersectPlane(Ray ray, Plane p, t_vec3 *hitNormal) +{ + float denom; + float t; + + denom = vec3_dot(p.normal, ray.dir); + if (fabs(denom) < 1e-6f) + return (-1); + t = vec3_dot(vec3_sub(p.point, ray.origin), p.normal) / denom; + if (t < 1e-3f) + return (-1); + *hitNormal = p.normal; + return (t); +} + +// Intersection d'un cylindre orienté arbitrairement (version simplifiée) +float intersectCylinder(Ray ray, Cylinder cy, t_vec3 *hitNormal) +{ + t_vec3 d; + t_vec3 oc; + t_vec3 v; + float d_dot_v; + float oc_dot_v; + t_vec3 d_perp; + t_vec3 oc_perp; + float a; + float b; + float c; + float disc; + float sqrtDisc; + float t0; + float t1; + float t_side; + float y; + float y; + float t_cap; + float t_bot; + t_vec3 p; + t_vec3 cp; + float dist; + float t_top; + t_vec3 p; + t_vec3 cp; + float dist; + float t_final; + t_vec3 hitPoint; + t_vec3 cp; + float proj; + t_vec3 n; + + d = ray.dir; + oc = vec3_sub(ray.origin, cy.center); + v = cy.axis; + d_dot_v = vec3_dot(d, v); + oc_dot_v = vec3_dot(oc, v); + d_perp = vec3_sub(d, vec3_scale(v, d_dot_v)); + oc_perp = vec3_sub(oc, vec3_scale(v, oc_dot_v)); + a = vec3_dot(d_perp, d_perp); + b = 2 * vec3_dot(d_perp, oc_perp); + c = vec3_dot(oc_perp, oc_perp) - cy.radius * cy.radius; + disc = b * b - 4 * a * c; + if (disc < 0) + return (-1); + sqrtDisc = sqrtf(disc); + t0 = (-b - sqrtDisc) / (2 * a); + t1 = (-b + sqrtDisc) / (2 * a); + t_side = -1; + if (t0 > 1e-3f) + { + y = oc_dot_v + t0 * d_dot_v; + if (fabs(y) <= cy.height / 2.0f) + t_side = t0; + } + if (t_side < 0 && t1 > 1e-3f) + { + y = oc_dot_v + t1 * d_dot_v; + if (fabs(y) <= cy.height / 2.0f) + t_side = t1; + } + t_cap = -1; + if (fabs(d_dot_v) > 1e-6f) + { + t_bot = ((-cy.height / 2.0f) - oc_dot_v) / d_dot_v; + if (t_bot > 1e-3f) + { + p = vec3_add(ray.origin, vec3_scale(d, t_bot)); + cp = vec3_sub(p, cy.center); + dist = vec3_length(vec3_sub(cp, vec3_scale(v, vec3_dot(cp, v)))); + if (dist <= cy.radius) + t_cap = t_bot; + } + t_top = ((cy.height / 2.0f) - oc_dot_v) / d_dot_v; + if (t_top > 1e-3f) + { + p = vec3_add(ray.origin, vec3_scale(d, t_top)); + cp = vec3_sub(p, cy.center); + dist = vec3_length(vec3_sub(cp, vec3_scale(v, vec3_dot(cp, v)))); + if (dist <= cy.radius && (t_cap < 0 || t_top < t_cap)) + t_cap = t_top; + } + } + t_final = -1; + if (t_side > 1e-3f && t_cap > 1e-3f) + t_final = (t_side < t_cap) ? t_side : t_cap; + else if (t_side > 1e-3f) + t_final = t_side; + else + t_final = t_cap; + if (t_final < 1e-3f) + return (-1); + hitPoint = vec3_add(ray.origin, vec3_scale(d, t_final)); + cp = vec3_sub(hitPoint, cy.center); + proj = vec3_dot(cp, v); + if (fabs(proj) < cy.height / 2.0f - 1e-3f) + { + n = vec3_sub(cp, vec3_scale(v, proj)); + *hitNormal = vec3_normalize(n); + } + else + { + *hitNormal = (proj > 0) ? v : vec3_scale(v, -1); + } + return t_final; +} + +// ----- Test d'ombre ----- +bool isInShadow(t_vec3 hitPoint, t_vec3 lightPos) +{ + t_vec3 toLight; + float maxT; + t_vec3 L; + const float epsilon = 1e-3f; + Ray shadowRay; + t_vec3 dummy; + float t; + + toLight = vec3_sub(lightPos, hitPoint); + maxT = vec3_length(toLight); + L = vec3_normalize(toLight); + shadowRay = {vec3_add(hitPoint, vec3_scale(L, epsilon)), L}; + for (int i = 0; i < numSpheres; i++) + { + t = intersectSphere(shadowRay, spheres[i], &dummy); + if (t > epsilon && t < maxT) + return true; + } + for (int i = 0; i < numPlanes; i++) + { + t = intersectPlane(shadowRay, planes[i], &dummy); + if (t > epsilon && t < maxT) + return true; + } + for (int i = 0; i < numCylinders; i++) + { + t = intersectCylinder(shadowRay, cylinders[i], &dummy); + if (t > epsilon && t < maxT) + return true; + } + return false; +} + +// ----- Lancer de rayon (ray tracing) ----- +t_vec3 trace(Ray ray) +{ + float tMin; + t_vec3 hitNormal; + t_vec3 objColor; + bool hitSomething; + float t; + t_vec3 n; + t_vec3 n; + t_vec3 n; + t_vec3 hitPoint; + t_vec3 finalColor; + Light light; + t_vec3 L; + float diff; + t_vec3 viewDir; + t_vec3 halfDir; + float spec; + + tMin = 1e9; + hitNormal = {0, 0, 0}; + objColor = {0, 0, 0}; + hitSomething = false; + for (int i = 0; i < numSpheres; i++) + { + t = intersectSphere(ray, spheres[i], &n); + if (t > 1e-3f && t < tMin) + { + tMin = t; + hitNormal = n; + objColor = spheres[i].color; + hitSomething = true; + } + } + for (int i = 0; i < numPlanes; i++) + { + t = intersectPlane(ray, planes[i], &n); + if (t > 1e-3f && t < tMin) + { + tMin = t; + hitNormal = n; + objColor = planes[i].color; + hitSomething = true; + } + } + for (int i = 0; i < numCylinders; i++) + { + t = intersectCylinder(ray, cylinders[i], &n); + if (t > 1e-3f && t < tMin) + { + tMin = t; + hitNormal = n; + objColor = cylinders[i].color; + hitSomething = true; + } + } + if (hitSomething) + { + hitPoint = vec3_add(ray.origin, vec3_scale(ray.dir, tMin)); + finalColor = vec3_scale(objColor, ambient_ratio); + for (int i = 0; i < numLights; i++) + { + light = lights[i]; + L = vec3_normalize(vec3_sub(light.pos, hitPoint)); + if (isInShadow(hitPoint, light.pos)) + continue ; + diff = fmaxf(0.0f, vec3_dot(hitNormal, L)); + viewDir = vec3_normalize(vec3_sub(camPos, hitPoint)); + halfDir = vec3_normalize(vec3_add(L, viewDir)); + spec = powf(fmaxf(0.0f, vec3_dot(hitNormal, halfDir)), 32.0f); + finalColor = vec3_add(finalColor, vec3_scale(vec3_mul(objColor, + light.color), diff * light.brightness)); + finalColor = vec3_add(finalColor, vec3_scale((t_vec3){1, 1, 1}, spec + * light.brightness)); + } + if (finalColor.x > 1.0f) + finalColor.x = 1.0f; + if (finalColor.y > 1.0f) + finalColor.y = 1.0f; + if (finalColor.z > 1.0f) + finalColor.z = 1.0f; + return finalColor; + } + return (t_vec3){0.2f, 0.7f, 1.0f}; // Fond (ciel) +} + +// ----- Main ----- +int main(int argc, char *argv[]) +{ + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; + Uint32 *pixels; + bool running; + SDL_Event event; + const float moveSpeed = 0.5f; + const float rotSpeed = 0.03f; + const float mouseSensitivity = 0.002f; + bool key_w = false, key_s = false, key_a = false, key_d; + bool key_left = false, key_right = false, key_up = false, + key_down; + t_vec3 right; + t_vec3 camUp; + float ndc_x; + float ndc_y; + float aspect; + float scale; + float screen_x; + float screen_y; + t_vec3 rayDir; + Ray ray; + t_vec3 color; + Uint8 r; + Uint8 g; + Uint8 b; + + // Chargement de la config si un fichier est passé en argument + if (argc > 1) + load_config(argv[1]); + // Scène par défaut si aucune config n'a été chargée + if (numSpheres == 0 && numPlanes == 0 && numCylinders == 0 + && numLights == 0) + { + spheres[0].center = (t_vec3){0, 0, 0}; + spheres[0].radius = 1.0f; + spheres[0].color = (t_vec3){1, 0, 0}; + numSpheres = 1; + planes[0].point = (t_vec3){0, -5, 0}; + planes[0].normal = (t_vec3){0, 1, 0}; + planes[0].color = (t_vec3){0, 1, 0}; + numPlanes = 1; + cylinders[0].center = (t_vec3){10, 0, 0}; + cylinders[0].axis = (t_vec3){0, 1, 0}; + cylinders[0].radius = 4.0f; + cylinders[0].height = 20.0f; + cylinders[0].color = (t_vec3){0, 0, 1}; + numCylinders = 1; + lights[0].pos = (t_vec3){0, 50, 20}; + lights[0].brightness = 1.0f; + lights[0].color = (t_vec3){1, 1, 1}; + numLights = 1; + ambient_ratio = 0.3f; + ambient_color = (t_vec3){1, 1, 1}; + camPos = (t_vec3){0, 0, 20}; + camDir = vec3_normalize((t_vec3){0, 0, -1}); + fov = 70.0f; + yaw = atan2f(camDir.x, -camDir.z); + pitch = asinf(camDir.y); + } + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + fprintf(stderr, "Erreur SDL_Init: %s\n", SDL_GetError()); + return 1; + } + window = SDL_CreateWindow("Raytracer interactif", SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, WIDTH * 2, HEIGHT * 2, SDL_WINDOW_SHOWN); + if (!window) + { + fprintf(stderr, "Erreur SDL_CreateWindow: %s\n", SDL_GetError()); + SDL_Quit(); + return 1; + } + SDL_SetRelativeMouseMode(SDL_TRUE); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + if (!renderer) + { + fprintf(stderr, "Erreur SDL_CreateRenderer: %s\n", SDL_GetError()); + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, WIDTH, HEIGHT); + if (!texture) + { + fprintf(stderr, "Erreur SDL_CreateTexture: %s\n", SDL_GetError()); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + pixels = malloc(WIDTH * HEIGHT * sizeof(Uint32)); + if (!pixels) + { + fprintf(stderr, "Erreur d'allocation mémoire.\n"); + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + running = true; + key_w = false, key_s = false, key_a = false, key_d = false; + key_left = false, key_right = false, key_up = false, key_down = false; + while (running) + { + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + running = false; + else if (event.type == SDL_KEYDOWN) + { + switch (event.key.keysym.sym) + { + case SDLK_ESCAPE: + running = false; + break ; + case SDLK_w: + key_w = true; + break ; + case SDLK_s: + key_s = true; + break ; + case SDLK_a: + key_a = true; + break ; + case SDLK_d: + key_d = true; + break ; + case SDLK_LEFT: + key_left = true; + break ; + case SDLK_RIGHT: + key_right = true; + break ; + case SDLK_UP: + key_up = true; + break ; + case SDLK_DOWN: + key_down = true; + break ; + default: + break ; + } + } + else if (event.type == SDL_KEYUP) + { + switch (event.key.keysym.sym) + { + case SDLK_w: + key_w = false; + break ; + case SDLK_s: + key_s = false; + break ; + case SDLK_a: + key_a = false; + break ; + case SDLK_d: + key_d = false; + break ; + case SDLK_LEFT: + key_left = false; + break ; + case SDLK_RIGHT: + key_right = false; + break ; + case SDLK_UP: + key_up = false; + break ; + case SDLK_DOWN: + key_down = false; + break ; + default: + break ; + } + } + else if (event.type == SDL_MOUSEMOTION) + { + yaw += event.motion.xrel * mouseSensitivity; + pitch -= event.motion.yrel * mouseSensitivity; + } + } + if (key_left) + yaw -= rotSpeed; + if (key_right) + yaw += rotSpeed; + if (key_up) + pitch += rotSpeed; + if (key_down) + pitch -= rotSpeed; + if (pitch > 1.57f - 0.01f) + pitch = 1.57f - 0.01f; + if (pitch < -1.57f + 0.01f) + pitch = -1.57f + 0.01f; + camDir.x = cosf(pitch) * sinf(yaw); + camDir.y = sinf(pitch); + camDir.z = -cosf(pitch) * cosf(yaw); + camDir = vec3_normalize(camDir); + right = {cosf(yaw), 0, sinf(yaw)}; + right = vec3_normalize(right); + camUp = vec3_normalize(vec3_cross(right, camDir)); + if (key_w) + camPos = vec3_add(camPos, vec3_scale(camDir, moveSpeed)); + if (key_s) + camPos = vec3_sub(camPos, vec3_scale(camDir, moveSpeed)); + if (key_a) + camPos = vec3_sub(camPos, vec3_scale(right, moveSpeed)); + if (key_d) + camPos = vec3_add(camPos, vec3_scale(right, moveSpeed)); + for (int y = 0; y < HEIGHT; y++) + { + for (int x = 0; x < WIDTH; x++) + { + ndc_x = (x + 0.5f) / WIDTH; + ndc_y = (y + 0.5f) / HEIGHT; + aspect = (float)WIDTH / HEIGHT; + scale = tanf((fov * 0.5f) * (M_PI / 180.0f)); + screen_x = (2 * ndc_x - 1) * aspect * scale; + screen_y = (1 - 2 * ndc_y) * scale; + rayDir = vec3_add(camDir, vec3_add(vec3_scale(right, screen_x), + vec3_scale(camUp, screen_y))); + rayDir = vec3_normalize(rayDir); + ray = {camPos, rayDir}; + color = trace(ray); + r = (Uint8)(fminf(color.x, 1.0f) * 255); + g = (Uint8)(fminf(color.y, 1.0f) * 255); + b = (Uint8)(fminf(color.z, 1.0f) * 255); + pixels[y * WIDTH + x] = (255 << 24) | (r << 16) | (g << 8) | b; + } + } + SDL_UpdateTexture(texture, NULL, pixels, WIDTH * sizeof(Uint32)); + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); + } + free(pixels); + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} diff --git a/tags b/tags new file mode 100644 index 0000000..8f790b3 --- /dev/null +++ b/tags @@ -0,0 +1,121 @@ +!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/ +!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/ +!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/ +!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/ +!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/ +!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/ +!_TAG_FIELD_DESCRIPTION input /input file/ +!_TAG_FIELD_DESCRIPTION name /tag name/ +!_TAG_FIELD_DESCRIPTION pattern /pattern/ +!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/ +!_TAG_FIELD_DESCRIPTION!C++ name /aliased names/ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_KIND_DESCRIPTION!C d,macro /macro definitions/ +!_TAG_KIND_DESCRIPTION!C e,enumerator /enumerators (values inside an enumeration)/ +!_TAG_KIND_DESCRIPTION!C f,function /function definitions/ +!_TAG_KIND_DESCRIPTION!C g,enum /enumeration names/ +!_TAG_KIND_DESCRIPTION!C h,header /included header files/ +!_TAG_KIND_DESCRIPTION!C m,member /struct, and union members/ +!_TAG_KIND_DESCRIPTION!C s,struct /structure names/ +!_TAG_KIND_DESCRIPTION!C t,typedef /typedefs/ +!_TAG_KIND_DESCRIPTION!C u,union /union names/ +!_TAG_KIND_DESCRIPTION!C v,variable /variable definitions/ +!_TAG_KIND_DESCRIPTION!C++ M,module /modules/ +!_TAG_KIND_DESCRIPTION!C++ P,partition /partitions/ +!_TAG_KIND_DESCRIPTION!C++ c,class /classes/ +!_TAG_KIND_DESCRIPTION!C++ d,macro /macro definitions/ +!_TAG_KIND_DESCRIPTION!C++ e,enumerator /enumerators (values inside an enumeration)/ +!_TAG_KIND_DESCRIPTION!C++ f,function /function definitions/ +!_TAG_KIND_DESCRIPTION!C++ g,enum /enumeration names/ +!_TAG_KIND_DESCRIPTION!C++ h,header /included header files/ +!_TAG_KIND_DESCRIPTION!C++ m,member /class, struct, and union members/ +!_TAG_KIND_DESCRIPTION!C++ n,namespace /namespaces/ +!_TAG_KIND_DESCRIPTION!C++ s,struct /structure names/ +!_TAG_KIND_DESCRIPTION!C++ t,typedef /typedefs/ +!_TAG_KIND_DESCRIPTION!C++ u,union /union names/ +!_TAG_KIND_DESCRIPTION!C++ v,variable /variable definitions/ +!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ +!_TAG_OUTPUT_FILESEP slash /slash or backslash/ +!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ +!_TAG_OUTPUT_VERSION 0.0 /current.age/ +!_TAG_PARSER_VERSION!C 1.1 /current.age/ +!_TAG_PARSER_VERSION!C++ 1.1 /current.age/ +!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/ +!_TAG_PROC_CWD /home/null/Documents/final/new_better_ray/ // +!_TAG_PROGRAM_AUTHOR Universal Ctags Team // +!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ +!_TAG_PROGRAM_URL https://ctags.io/ /official site/ +!_TAG_PROGRAM_VERSION 6.1.0 /653ca9204/ +!_TAG_ROLE_DESCRIPTION!C!function foreigndecl /declared in foreign languages/ +!_TAG_ROLE_DESCRIPTION!C!header local /local header/ +!_TAG_ROLE_DESCRIPTION!C!header system /system header/ +!_TAG_ROLE_DESCRIPTION!C!macro undef /undefined/ +!_TAG_ROLE_DESCRIPTION!C!struct foreigndecl /declared in foreign languages/ +!_TAG_ROLE_DESCRIPTION!C++!header exported /exported with "exported imported ..."/ +!_TAG_ROLE_DESCRIPTION!C++!header imported /imported with "imported ..."/ +!_TAG_ROLE_DESCRIPTION!C++!header local /local header/ +!_TAG_ROLE_DESCRIPTION!C++!header system /system header/ +!_TAG_ROLE_DESCRIPTION!C++!macro undef /undefined/ +!_TAG_ROLE_DESCRIPTION!C++!module imported /imported with "imported ..."/ +!_TAG_ROLE_DESCRIPTION!C++!module partOwner /used for specifying a partition/ +!_TAG_ROLE_DESCRIPTION!C++!partition imported /imported with "imported ..."/ +HEIGHT miniRT.h /^# define HEIGHT /;" d +MAX_CYLINDERS miniRT.h /^# define MAX_CYLINDERS /;" d +MAX_LIGHTS miniRT.h /^# define MAX_LIGHTS /;" d +MAX_PLANES miniRT.h /^# define MAX_PLANES /;" d +MAX_SPHERES miniRT.h /^# define MAX_SPHERES /;" d +MINIRT_H miniRT.h /^# define MINIRT_H$/;" d +WIDTH miniRT.h /^# define WIDTH /;" d +ambient_color raytracer_formatted.c /^t_vec3 ambient_color = {0.1f, 0.1f, 0.1f};$/;" v typeref:typename:t_vec3 +ambient_ratio raytracer_formatted.c /^float ambient_ratio = 0.1f;$/;" v typeref:typename:float +axis miniRT.h /^ t_vec3 axis;\/\/ Axe normalisé$/;" m struct:s_vec3 typeref:typename:t_vec3 +brightness miniRT.h /^ float brightness;$/;" m struct:s_vec3 typeref:typename:float +camDir raytracer_formatted.c /^t_vec3 camDir = {0.0f, 0.0f, -1.0f};$/;" v typeref:typename:t_vec3 +camPos raytracer_formatted.c /^t_vec3 camPos = {0.0f, 0.0f, 0.0f};$/;" v typeref:typename:t_vec3 +center miniRT.h /^ t_vec3 center;$/;" m struct:s_vec3 typeref:typename:t_vec3 +color miniRT.h /^ t_vec3 color;$/;" m struct:s_vec3 typeref:typename:t_vec3 +cylinders raytracer_formatted.c /^Cylinder cylinders[MAX_CYLINDERS];$/;" v typeref:typename:Cylinder[] +dir miniRT.h /^ t_vec3 dir;$/;" m struct:s_vec3 typeref:typename:t_vec3 +fov raytracer_formatted.c /^float fov = 90.0f;$/;" v typeref:typename:float +height miniRT.h /^ float height;$/;" m struct:s_vec3 typeref:typename:float +intersectCylinder raytracer_formatted.c /^float intersectCylinder(Ray ray, Cylinder cy, t_vec3 *hitNormal)$/;" f typeref:typename:float +intersectPlane raytracer_formatted.c /^float intersectPlane(Ray ray, Plane p, t_vec3 *hitNormal)$/;" f typeref:typename:float +intersectSphere raytracer_formatted.c /^float intersectSphere(Ray ray, Sphere s, t_vec3 *hitNormal)$/;" f typeref:typename:float +isInShadow raytracer_formatted.c /^bool isInShadow(t_vec3 hitPoint, t_vec3 lightPos)$/;" f typeref:typename:bool +lights raytracer_formatted.c /^Light lights[MAX_LIGHTS];$/;" v typeref:typename:Light[] +load_config raytracer_formatted.c /^void load_config(const char *filename)$/;" f typeref:typename:void +main raytracer_formatted.c /^int main(int argc, char *argv[])$/;" f typeref:typename:int +normal miniRT.h /^ t_vec3 normal;$/;" m struct:s_vec3 typeref:typename:t_vec3 +numCylinders raytracer_formatted.c /^int numCylinders = 0;$/;" v typeref:typename:int +numLights raytracer_formatted.c /^int numLights = 0;$/;" v typeref:typename:int +numPlanes raytracer_formatted.c /^int numPlanes = 0;$/;" v typeref:typename:int +numSpheres raytracer_formatted.c /^int numSpheres = 0;$/;" v typeref:typename:int +origin miniRT.h /^ t_vec3 origin;$/;" m struct:s_vec3 typeref:typename:t_vec3 +pitch raytracer_formatted.c /^float yaw = 0.0f, pitch = 0.0f; \/\/ en radians$/;" v typeref:typename:float +planes raytracer_formatted.c /^Plane planes[MAX_PLANES];$/;" v typeref:typename:Plane[] +point miniRT.h /^ t_vec3 point;$/;" m struct:s_vec3 typeref:typename:t_vec3 +pos miniRT.h /^ t_vec3 pos;$/;" m struct:s_vec3 typeref:typename:t_vec3 +radius miniRT.h /^ float radius;$/;" m struct:s_vec3 typeref:typename:float +radius miniRT.h /^ float radius;\/\/ Demi-diamètre$/;" m struct:s_vec3 typeref:typename:float +s_vec3 miniRT.h /^typedef struct s_vec3$/;" s +spheres raytracer_formatted.c /^Sphere spheres[MAX_SPHERES];$/;" v typeref:typename:Sphere[] +t_cylinder miniRT.h /^} t_cylinder;$/;" t typeref:struct:s_vec3 +t_light miniRT.h /^} t_light;$/;" t typeref:struct:s_vec3 +t_plane miniRT.h /^} t_plane;$/;" t typeref:struct:s_vec3 +t_ray miniRT.h /^} t_ray;$/;" t typeref:struct:s_vec3 +t_sphere miniRT.h /^} t_sphere;$/;" t typeref:struct:s_vec3 +t_vec3 miniRT.h /^} t_vec3;$/;" t typeref:struct:s_vec3 +trace raytracer_formatted.c /^t_vec3 trace(Ray ray)$/;" f typeref:typename:t_vec3 +vec3_add calcul_de_vecteur.c /^t_vec3 vec3_add(t_vec3 a, t_vec3 b)$/;" f typeref:typename:t_vec3 +vec3_cross calcul_de_vecteur.c /^t_vec3 vec3_cross(t_vec3 a, t_vec3 b)$/;" f typeref:typename:t_vec3 +vec3_dot calcul_de_vecteur.c /^float vec3_dot(t_vec3 a, t_vec3 b)$/;" f typeref:typename:float +vec3_length calcul_de_vecteur.c /^float vec3_length(t_vec3 a)$/;" f typeref:typename:float +vec3_mul calcul_de_vecteur.c /^t_vec3 vec3_mul(t_vec3 a, t_vec3 b)$/;" f typeref:typename:t_vec3 +vec3_normalize calcul_de_vecteur.c /^t_vec3 vec3_normalize(t_vec3 a)$/;" f typeref:typename:t_vec3 +vec3_scale calcul_de_vecteur.c /^t_vec3 vec3_scale(t_vec3 a, float s)$/;" f typeref:typename:t_vec3 +vec3_sub calcul_de_vecteur.c /^t_vec3 vec3_sub(t_vec3 a, t_vec3 b)$/;" f typeref:typename:t_vec3 +x miniRT.h /^ float x;$/;" m struct:s_vec3 typeref:typename:float +y miniRT.h /^ float y;$/;" m struct:s_vec3 typeref:typename:float +yaw raytracer_formatted.c /^float yaw = 0.0f, pitch = 0.0f; \/\/ en radians$/;" v typeref:typename:float +z miniRT.h /^ float z;$/;" m struct:s_vec3 typeref:typename:float