diff --git a/README.md b/README.md index 0536069..f6e3ead 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,45 @@ add_math_surface(uni, 0, 0, 0, int_to_f(120), int_to_f(120), 30, 30, COLOR6, 0, --- +## Manipulation des Mesh + +Une fois générés, les objets peuvent être positionnés, transformés ou recolorés à l'aide des fonctions suivantes (définies dans `engine.c` / `geometry.c`) : + +* **`void set_object_pos(Object3D *obj, fixed x, fixed y, fixed z);`** + +``` +void set_object_pos (Object3D *obj, fixed x, fixed y, fixed z); +``` + +Définit la position locale absolue de l'objet (`base_pos`) par rapport au centre de son espace d'orbite. + +* **`void move_object(Object3D *obj, fixed dx, fixed dy, fixed dz);`** + +``` +void move_object (Object3D *obj, fixed dx, fixed dy, fixed dz); +``` + +Applique une translation relative à l'objet en ajoutant le décalage spécifié à sa position courante. + +* **`void set_object_color(Object3D *obj, uint8_t col);`** + +``` +void set_object_color (Object3D *obj, uint8_t col); +``` + +Modifie l'index de couleur de base (0-15) utilisé pour le rendu de l'ensemble des faces de l'objet. + +* **`void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az);`** + +``` +void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az); +``` + +Applique une rotation *permanente* (Baking) aux sommets et aux normales de l'objet directement dans le pool de l'univers. +Particulièrement utile pour orienter une primitive lors de l'initialisation (ex: coucher un cylindre sur le flanc) sans induire le moindre coût de calcul matriciel supplémentaire pendant la boucle de rendu en temps réel. + +--- + ## Orbite de l'observateur (`main.c`) Les objets ont des positions de base fixes dans l'espace scène, définies par rapport au centre `(0, 0, 300)` : diff --git a/src/part3D/defines.h b/src/part3D/defines.h index ae73d9c..7bd83f5 100644 --- a/src/part3D/defines.h +++ b/src/part3D/defines.h @@ -81,7 +81,12 @@ typedef struct { } Camera; /* Mesh dynamique conservé pour save/load uniquement */ -typedef struct { Vector3 *verts; Vector3 *v_normals; Face *faces; int num_verts, num_faces; } Mesh; +typedef struct { + Vector3 *verts; + Vector3 *v_normals; + Face *faces; + int num_verts, num_faces; +} Mesh; /* Globales */ extern fixed sintab[360], costab[360]; @@ -101,9 +106,10 @@ 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); +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); +void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az); /* Retournent un pointeur sur le nouvel Object3D, NULL si pool saturé */ Object3D* add_box (Universe *uni, fixed x, fixed y, fixed z, fixed dx, fixed dy, fixed dz, uint8_t col, uint8_t wire); diff --git a/src/part3D/engine.c b/src/part3D/engine.c index 8780bc1..4e05fd9 100644 --- a/src/part3D/engine.c +++ b/src/part3D/engine.c @@ -34,14 +34,71 @@ void mat3_rotate_x(Matrix3 *m, int angle) { int a = ((angle % 360) + 360) % 360; fixed c = costab[a], s = sintab[a]; mat3_identity(m); - m->m[1][1] = c; m->m[1][2] = -s; m->m[2][1] = s; m->m[2][2] = c; + m->m[1][1] = c; + m->m[1][2] = -s; + m->m[2][1] = s; + m->m[2][2] = c; } void mat3_rotate_y(Matrix3 *m, int angle) { int a = ((angle % 360) + 360) % 360; fixed c = costab[a], s = sintab[a]; mat3_identity(m); - m->m[0][0] = c; m->m[0][2] = s; m->m[2][0] = -s; m->m[2][2] = c; + m->m[0][0] = c; + m->m[0][2] = s; + m->m[2][0] = -s; + m->m[2][2] = c; +} + +void mat3_rotate_z(Matrix3 *m, int angle) { + int a = ((angle % 360) + 360) % 360; + fixed c = costab[a], s = sintab[a]; + mat3_identity(m); + m->m[0][0] = c; + m->m[0][1] = s; + m->m[1][0] = -s; + m->m[1][1] = c; +} + +/* Fait pivoter la géométrie locale de l'objet de façon permanente */ +void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az) { + Matrix3 rx, ry, rz, tmp, rot; + Vector3 *v, *n; + + int i, vi; + fixed vx, vy, vz; + + if (!obj || !uni) return; + + /* Composition de la matrice de rotation */ + mat3_rotate_x(&rx, ax); + mat3_rotate_y(&ry, ay); + mat3_rotate_z(&rz, az); + mat3_mul(&tmp, &rx, &ry); + mat3_mul(&rot, &tmp, &rz); + + /* Application à tous les sommets et normales de l'objet */ + for (i = 0; i < obj->num_verts; i++) { + vi = obj->vert_start + i; + v = &uni->verts[vi]; + n = &uni->v_normals[vi]; + + /* Sommets */ + vx = f_mul(v->x, rot.m[0][0]) + f_mul(v->y, rot.m[1][0]) + f_mul(v->z, rot.m[2][0]); + vy = f_mul(v->x, rot.m[0][1]) + f_mul(v->y, rot.m[1][1]) + f_mul(v->z, rot.m[2][1]); + vz = f_mul(v->x, rot.m[0][2]) + f_mul(v->y, rot.m[1][2]) + f_mul(v->z, rot.m[2][2]); + v->x = vx; + v->y = vy; + v->z = vz; + + /* Normales (doivent aussi pivoter pour l'ombrage Gouraud !) */ + vx = f_mul(n->x, rot.m[0][0]) + f_mul(n->y, rot.m[1][0]) + f_mul(n->z, rot.m[2][0]); + vy = f_mul(n->x, rot.m[0][1]) + f_mul(n->y, rot.m[1][1]) + f_mul(n->z, rot.m[2][1]); + vz = f_mul(n->x, rot.m[0][2]) + f_mul(n->y, rot.m[1][2]) + f_mul(n->z, rot.m[2][2]); + n->x = vx; + n->y = vy; + n->z = vz; + } } void render_universe(Universe *uni, Camera *cam, int mode) {