From a45540412c2030e2e4877515b0ecc4634edf5818 Mon Sep 17 00:00:00 2001 From: Frater <13979047+saintfrater@users.noreply.github.com> Date: Sun, 10 May 2026 13:29:07 +0200 Subject: [PATCH] add primitives --- src/main/main.c | 24 ++-- src/part3D/defines.h | 13 +- src/part3D/geometry.c | 285 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+), 13 deletions(-) diff --git a/src/main/main.c b/src/main/main.c index 2aaf06d..5f6e2fa 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -2,7 +2,7 @@ int main(void) { Universe *uni; - Object3D *sph, *cyl; + Object3D *sph, *cyl, *tmp_obj; Camera cam; Matrix3 rotX, rotY, orbit; int anglex, angley, key, render, o; @@ -19,19 +19,21 @@ int main(void) { uni->num_verts = uni->num_faces = uni->num_objects = 0; /* --- Ajout des objets : géométrie locale en (0,0,0) --- */ - sph = add_sphere(uni, 0, 0, 0, int_to_f(30), 8, COLOR5, 0); + /* + sph = add_sphere(uni, 0, 0, 0, int_to_f(30), 8, COLOR4, 0); if (!sph) { free(uni); return 1; } - sph->base_pos.x = int_to_f(60); /* offset par rapport au centre d'orbite (0,0,300) */ - sph->base_pos.y = 0; - sph->base_pos.z = 0; - sph->color = COLOR4; /* jaune */ + set_object_pos(sph,int_to_f(60),0,0); + //set_object_color(COLOR4); - cyl = add_cylinder(uni, 0, 0, 0, int_to_f(20), int_to_f(60), 12, COLOR14, 0); + cyl = add_cylinder(uni, 0, 0, 0, int_to_f(20), int_to_f(60), 12, COLOR2, 0); if (!cyl) { free(uni); return 1; } - cyl->base_pos.x = int_to_f(-60); - cyl->base_pos.y = 0; - cyl->base_pos.z = 0; - cyl->color = COLOR2; /* vert */ + set_object_pos(cyl,int_to_f(-60),0,0); + //set_object_color(COLOR2); + */ + + tmp_obj = add_math_surface(uni, 0, 0, 0, int_to_f(120), int_to_f(120), 30, 30, COLOR2, 0); + // set_object_pos(tmp_obj, 0, int_to_f(-40), 0); + /* Pour ajouter un troisième objet : */ /* diff --git a/src/part3D/defines.h b/src/part3D/defines.h index 4f81193..720a6bf 100644 --- a/src/part3D/defines.h +++ b/src/part3D/defines.h @@ -93,9 +93,18 @@ void mat3_rotate_x(Matrix3 *m, int angle); void mat3_rotate_y(Matrix3 *m, int angle); void mat3_mul(Matrix3 *res, Matrix3 *a, Matrix3 *b); +void set_object_pos(Object3D *obj, fixed x, fixed y, fixed z); +void move_object(Object3D *obj, fixed dx, fixed dy, fixed dz); +void set_object_color(Object3D *obj, uint8_t col); + /* Retournent un pointeur sur le nouvel Object3D, NULL si pool saturé */ -Object3D* add_sphere (Universe *uni, fixed x, fixed y, fixed z, fixed r, int det, uint8_t col, uint8_t wire); -Object3D* add_cylinder(Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, int det, uint8_t col, uint8_t wire); +Object3D* add_box (Universe *uni, fixed x, fixed y, fixed z, fixed dx, fixed dy, fixed dz, uint8_t col, uint8_t wire); +Object3D* add_sphere (Universe *uni, fixed x, fixed y, fixed z, fixed r, int det, uint8_t col, uint8_t wire); +Object3D* add_cylinder (Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, int det, uint8_t col, uint8_t wire); +Object3D* add_cone (Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, int det, uint8_t col, uint8_t wire); +Object3D* add_plane (Universe *uni, fixed x, fixed y, fixed z, fixed w, fixed d, int seg_x, int seg_z, uint8_t col, uint8_t wire); +Object3D* add_math_surface(Universe *uni, fixed x, fixed y, fixed z, fixed w, fixed d, int seg_x, int seg_z, uint8_t col, uint8_t wire); +Object3D* add_torus (Universe *uni, fixed x, fixed y, fixed z, fixed r_main, fixed r_tube, int seg_main, int seg_tube, uint8_t col, uint8_t wire); void render_universe(Universe *uni, Camera *cam, int mode); diff --git a/src/part3D/geometry.c b/src/part3D/geometry.c index 8f1a23c..5130191 100644 --- a/src/part3D/geometry.c +++ b/src/part3D/geometry.c @@ -19,6 +19,69 @@ static Object3D *alloc_object(Universe *uni) { return obj; } +/* Déplacement absolu : fixe la position de l'objet dans l'espace de l'orbite */ +void set_object_pos(Object3D *obj, fixed x, fixed y, fixed z) { + if (!obj) return; + obj->base_pos.x = x; + obj->base_pos.y = y; + obj->base_pos.z = z; +} + +/* Déplacement relatif : ajoute un décalage à la position actuelle */ +void move_object(Object3D *obj, fixed dx, fixed dy, fixed dz) { + if (!obj) return; + obj->base_pos.x += dx; + obj->base_pos.y += dy; + obj->base_pos.z += dz; +} + +/* Changement de couleur */ +void set_object_color(Object3D *obj, uint8_t col) { + if (!obj) return; + obj->color = col; +} + +Object3D *add_box(Universe *uni, fixed x, fixed y, fixed z, fixed dx, fixed dy, fixed dz, uint8_t col, uint8_t wire) { + int i, j, v_base; + Object3D *obj; + fixed hx = dx / 2, hy = dy / 2, hz = dz / 2; + + /* Normales des 6 faces : +Z, -Z, +Y, -Y, +X, -X */ + fixed nx[6] = {0, 0, 0, 0, int_to_f(1), -int_to_f(1)}; + fixed ny[6] = {0, 0, int_to_f(1), -int_to_f(1), 0, 0}; + fixed nz[6] = {int_to_f(1), -int_to_f(1), 0, 0, 0, 0}; + + /* Configuration des sommets pour respecter le "face culling" (sens trigo) */ + int sx[24] = {-1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1}; + int sy[24] = {-1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1}; + int sz[24] = { 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1}; + + if (uni->num_objects >= MAX_OBJECTS) return NULL; + if (uni->num_verts + 24 > MAX_VERTEX) return NULL; + if (uni->num_faces + 12 > MAX_FACES) return NULL; + + obj = alloc_object(uni); + obj->color = col; + v_base = uni->num_verts; + + for (i = 0; i < 6; i++) { + for(j = 0; j < 4; j++) { + int idx = i * 4 + j; + uni->v_normals[uni->num_verts].x = nx[i]; + uni->v_normals[uni->num_verts].y = ny[i]; + uni->v_normals[uni->num_verts].z = nz[i]; + uni->verts[uni->num_verts].x = x + (sx[idx] > 0 ? hx : -hx); + uni->verts[uni->num_verts].y = y + (sy[idx] > 0 ? hy : -hy); + uni->verts[uni->num_verts].z = z + (sz[idx] > 0 ? hz : -hz); + uni->num_verts++; obj->num_verts++; + } + /* Deux triangles par face */ + push_face(uni, obj, v_base + i * 4, v_base + i * 4 + 1, v_base + i * 4 + 2, wire); + push_face(uni, obj, v_base + i * 4, v_base + i * 4 + 2, v_base + i * 4 + 3, wire); + } + return obj; +} + Object3D *add_sphere(Universe *uni, fixed x, fixed y, fixed z, fixed r, int det, uint8_t col, uint8_t wire) { int i, j, v_base, phi, th; Object3D *obj; @@ -63,6 +126,228 @@ Object3D *add_sphere(Universe *uni, fixed x, fixed y, fixed z, fixed r, int det, return obj; } +Object3D *add_cone(Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, int det, uint8_t col, uint8_t wire) { + int i, v_base, cap_bot_center, cap_bot_rim, th; + fixed half_h, s, cs; + Object3D *obj; + + if (uni->num_objects >= MAX_OBJECTS) return NULL; + if (uni->num_verts + 1 + 3 * det > MAX_VERTEX) return NULL; + if (uni->num_faces + 2 * det > MAX_FACES) return NULL; + + obj = alloc_object(uni); + obj->color = col; + v_base = uni->num_verts; + half_h = h / 2; + + /* --- Corps --- */ + for (i = 0; i < det; i++) { + th = (i * 360 / det) % 360; + s = sintab[th]; cs = costab[th]; + + /* Base du corps */ + uni->v_normals[uni->num_verts].x = cs; + uni->v_normals[uni->num_verts].y = 0; + uni->v_normals[uni->num_verts].z = s; + uni->verts[uni->num_verts].x = x + f_mul(r, cs); + uni->verts[uni->num_verts].y = y - half_h; + uni->verts[uni->num_verts].z = z + f_mul(r, s); + uni->num_verts++; obj->num_verts++; + + /* Pointe du corps (dupliquée par face pour préserver les normales) */ + uni->v_normals[uni->num_verts].x = cs; + uni->v_normals[uni->num_verts].y = 0; + uni->v_normals[uni->num_verts].z = s; + uni->verts[uni->num_verts].x = x; + uni->verts[uni->num_verts].y = y + half_h; + uni->verts[uni->num_verts].z = z; + uni->num_verts++; obj->num_verts++; + } + + for (i = 0; i < det; i++) { + int a = v_base + (i * 2); + int b = v_base + ((i * 2 + 2) % (det * 2)); + int cv = a + 1; + push_face(uni, obj, a, cv, b, wire); + } + + /* --- Fond bas --- */ + cap_bot_center = uni->num_verts; + uni->v_normals[uni->num_verts].x = 0; + uni->v_normals[uni->num_verts].y = -int_to_f(1); + uni->v_normals[uni->num_verts].z = 0; + uni->verts[uni->num_verts].x = x; + uni->verts[uni->num_verts].y = y - half_h; + uni->verts[uni->num_verts].z = z; + uni->num_verts++; obj->num_verts++; + + cap_bot_rim = uni->num_verts; + for (i = 0; i < det; i++) { + th = (i * 360 / det) % 360; + s = sintab[th]; cs = costab[th]; + uni->v_normals[uni->num_verts].x = 0; + uni->v_normals[uni->num_verts].y = -int_to_f(1); + uni->v_normals[uni->num_verts].z = 0; + uni->verts[uni->num_verts].x = x + f_mul(r, cs); + uni->verts[uni->num_verts].y = y - half_h; + uni->verts[uni->num_verts].z = z + f_mul(r, s); + uni->num_verts++; obj->num_verts++; + } + + for (i = 0; i < det; i++) + push_face(uni, obj, cap_bot_center, cap_bot_rim + i, cap_bot_rim + (i + 1) % det, wire); + + return obj; +} + +Object3D *add_plane(Universe *uni, fixed x, fixed y, fixed z, fixed w, fixed d, int seg_x, int seg_z, uint8_t col, uint8_t wire) { + int i, j, v_base; + Object3D *obj; + fixed h_w = w / 2, h_d = d / 2; + fixed step_x, step_z; + + if (seg_x < 1) seg_x = 1; + if (seg_z < 1) seg_z = 1; + if (uni->num_objects >= MAX_OBJECTS) return NULL; + if (uni->num_verts + (seg_x + 1) * (seg_z + 1) > MAX_VERTEX) return NULL; + if (uni->num_faces + seg_x * seg_z * 2 > MAX_FACES) return NULL; + + obj = alloc_object(uni); + obj->color = col; + v_base = uni->num_verts; + + step_x = w / seg_x; + step_z = d / seg_z; + + for (j = 0; j <= seg_z; j++) { + for (i = 0; i <= seg_x; i++) { + uni->v_normals[uni->num_verts].x = 0; + uni->v_normals[uni->num_verts].y = int_to_f(1); + uni->v_normals[uni->num_verts].z = 0; + uni->verts[uni->num_verts].x = x - h_w + i * step_x; + uni->verts[uni->num_verts].y = y; + uni->verts[uni->num_verts].z = z - h_d + j * step_z; + uni->num_verts++; obj->num_verts++; + } + } + + for (j = 0; j < seg_z; j++) { + for (i = 0; i < seg_x; i++) { + int a = v_base + j * (seg_x + 1) + i; + int b = a + 1; + int c = v_base + (j + 1) * (seg_x + 1) + i; + int d_idx = c + 1; + /* Triangulation (a,c,b) et (b,c,d_idx) pour garantir une normale face +Y */ + push_face(uni, obj, a, c, b, wire); + push_face(uni, obj, b, c, d_idx, wire); + } + } + return obj; +} + +Object3D *add_math_surface(Universe *uni, fixed x, fixed y, fixed z, fixed w, fixed d, int seg_x, int seg_z, uint8_t col, uint8_t wire) { + int i, j, v_base; + Object3D *obj; + fixed h_w = w / 2, h_d = d / 2; + fixed step_x, step_z; + + if (seg_x < 1) seg_x = 1; if (seg_z < 1) seg_z = 1; + if (uni->num_objects >= MAX_OBJECTS) return NULL; + if (uni->num_verts + (seg_x + 1) * (seg_z + 1) > MAX_VERTEX) return NULL; + if (uni->num_faces + seg_x * seg_z * 2 > MAX_FACES) return NULL; + + obj = alloc_object(uni); obj->color = col; v_base = uni->num_verts; + step_x = w / seg_x; step_z = d / seg_z; + + for (j = 0; j <= seg_z; j++) { + for (i = 0; i <= seg_x; i++) { + fixed vx = x - h_w + i * step_x; + fixed vz = z - h_d + j * step_z; + + /* --- Application de la formule mathématique --- */ + /* 1. Conversion en flottant pour éviter les débordements avec x*x */ + double dx = (double)(vx - x) / 65536.0; + double dz = (double)(vz - z) / 65536.0; + + /* 2. La formule : Y = Amplitude * sin(Fréquence * sqrt(X^2 + Z^2)) */ + double dist = sqrt(dx * dx + dz * dz); + double fy = 20.0 * sin(dist / 10.0); /* 20.0 = amplitude, 10.0 = étalement */ + + uni->verts[uni->num_verts].x = vx; + uni->verts[uni->num_verts].y = y + (fixed)(fy * 65536.0); + uni->verts[uni->num_verts].z = vz; + + /* Normale provisoire vers le haut */ + uni->v_normals[uni->num_verts].x = 0; + uni->v_normals[uni->num_verts].y = int_to_f(1); + uni->v_normals[uni->num_verts].z = 0; + uni->num_verts++; obj->num_verts++; + } + } + + /* Génération des faces (identique au plan) */ + for (j = 0; j < seg_z; j++) { + for (i = 0; i < seg_x; i++) { + int a = v_base + j * (seg_x + 1) + i; + int b = a + 1; + int c = v_base + (j + 1) * (seg_x + 1) + i; + push_face(uni, obj, a, c, b, wire); + push_face(uni, obj, b, c, c + 1, wire); + } + } + return obj; +} + +Object3D *add_torus(Universe *uni, fixed x, fixed y, fixed z, fixed r_main, fixed r_tube, int seg_main, int seg_tube, uint8_t col, uint8_t wire) { + int i, j, v_base; + Object3D *obj; + + if (uni->num_objects >= MAX_OBJECTS) return NULL; + if (uni->num_verts + seg_main * seg_tube > MAX_VERTEX) return NULL; + if (uni->num_faces + seg_main * seg_tube * 2 > MAX_FACES) return NULL; + + obj = alloc_object(uni); + obj->color = col; + v_base = uni->num_verts; + + for (i = 0; i < seg_main; i++) { + int th_main = (i * 360 / seg_main) % 360; + fixed cos_u = costab[th_main]; + fixed sin_u = sintab[th_main]; + + for (j = 0; j < seg_tube; j++) { + int th_tube = (j * 360 / seg_tube) % 360; + fixed cos_v = costab[th_tube]; + fixed sin_v = sintab[th_tube]; + fixed dist = r_main + f_mul(r_tube, cos_v); + + uni->v_normals[uni->num_verts].x = f_mul(cos_v, cos_u); + uni->v_normals[uni->num_verts].y = sin_v; + uni->v_normals[uni->num_verts].z = f_mul(cos_v, sin_u); + + uni->verts[uni->num_verts].x = x + f_mul(dist, cos_u); + uni->verts[uni->num_verts].y = y + f_mul(r_tube, sin_v); + uni->verts[uni->num_verts].z = z + f_mul(dist, sin_u); + uni->num_verts++; obj->num_verts++; + } + } + + for (i = 0; i < seg_main; i++) { + int next_i = (i + 1) % seg_main; + for (j = 0; j < seg_tube; j++) { + int next_j = (j + 1) % seg_tube; + int a = v_base + i * seg_tube + j; + int b = v_base + next_i * seg_tube + j; + int c = v_base + i * seg_tube + next_j; + int d = v_base + next_i * seg_tube + next_j; + + push_face(uni, obj, a, c, b, wire); + push_face(uni, obj, b, c, d, wire); + } + } + return obj; +} + Object3D *add_cylinder(Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, int det, uint8_t col, uint8_t wire) { int i, v_base, cap_bot_center, cap_bot_rim, cap_top_center, cap_top_rim, th; fixed half_h, s, cs;