parametrage de math_surf
This commit is contained in:
parent
a45540412c
commit
b1c8be9dd6
3 changed files with 69 additions and 32 deletions
36
README.md
36
README.md
|
|
@ -155,6 +155,42 @@ Paramètres : centre local, rayon `r`, hauteur `h`, détail `det`.
|
||||||
|
|
||||||
**Total par cylindre (det=16) :** 2+4×det = 66 sommets, 4×det = 64 faces.
|
**Total par cylindre (det=16) :** 2+4×det = 66 sommets, 4×det = 64 faces.
|
||||||
|
|
||||||
|
### Boîte / Cube (`add_box`)
|
||||||
|
Paramètres : centre local, dimensions indépendantes `dx, dy, dz`.
|
||||||
|
Génère 24 sommets (4 par face pour ne pas lisser les arêtes avec Gouraud) et 12 faces.
|
||||||
|
Normales : alignées sur les axes orthogonaux (±X, ±Y, ±Z).
|
||||||
|
|
||||||
|
### Cône (`add_cone`)
|
||||||
|
Paramètres : centre local, rayon `r`, hauteur `h`, détail `det`.
|
||||||
|
Dérivé du cylindre, mais la boucle supérieure converge en un point unique avec des sommets dupliqués pour préserver l'interpolation radiale des normales du corps. Ne possède qu'un "fond bas".
|
||||||
|
|
||||||
|
### Plan / Grille (`add_plane`)
|
||||||
|
Paramètres : centre local, largeur `w`, profondeur `d`, segments `seg_x`, `seg_z`.
|
||||||
|
Génère une surface plane subdivisée (idéal pour les sols et l'ombrage Gouraud par point).
|
||||||
|
Normales : dirigées vers le haut (+Y).
|
||||||
|
|
||||||
|
### Tore (`add_torus`)
|
||||||
|
Paramètres : centre local, rayon principal `r_main`, rayon du tube `r_tube`, subdivisions `seg_main`, `seg_tube`.
|
||||||
|
Génère un anneau ("donut") via deux boucles trigonométriques imbriquées. Excellente primitive de test pour l'éclairage.
|
||||||
|
|
||||||
|
### Surface Mathématique (`add_math_surface`)
|
||||||
|
Paramètres : similaires au plan, plus un pointeur de fonction `SurfaceFunc`.
|
||||||
|
Cette primitive génère une grille dont la hauteur Y est calculée dynamiquement par la fonction utilisateur passée en paramètre.
|
||||||
|
La fonction utilisateur doit respecter la signature : `fixed ma_fonction(fixed x, fixed z)`.
|
||||||
|
|
||||||
|
```
|
||||||
|
/* Exemple de formule : le "Sombrero" */
|
||||||
|
fixed mon_onde(fixed x, fixed z) {
|
||||||
|
double dx = (double)x / 65536.0;
|
||||||
|
double dz = (double)z / 65536.0;
|
||||||
|
double dist = sqrt(dx * dx + dz * dz);
|
||||||
|
return (fixed)(20.0 * sin(dist / 10.0) * 65536.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Appel dans le main */
|
||||||
|
add_math_surface(uni, 0, 0, 0, int_to_f(120), int_to_f(120), 30, 30, COLOR6, 0, mon_onde);
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Orbite de l'observateur (`main.c`)
|
## Orbite de l'observateur (`main.c`)
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,10 @@ extern uint16_t *zbuffer;
|
||||||
extern uint8_t *vga;
|
extern uint8_t *vga;
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
|
|
||||||
|
/* Type pour les fonctions de génération de surface : reçoit x, z et renvoie y */
|
||||||
|
typedef fixed (*SurfaceFunc)(fixed x, fixed z);
|
||||||
|
|
||||||
void init_engine_math(void);
|
void init_engine_math(void);
|
||||||
void mat3_identity(Matrix3 *mat);
|
void mat3_identity(Matrix3 *mat);
|
||||||
void mat3_rotate_x(Matrix3 *m, int angle);
|
void mat3_rotate_x(Matrix3 *m, int angle);
|
||||||
|
|
@ -103,8 +107,10 @@ Object3D* add_sphere (Universe *uni, fixed x, fixed y, fixed z, fixed r,
|
||||||
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_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_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_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);
|
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);
|
||||||
|
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, SurfaceFunc func);
|
||||||
|
|
||||||
void render_universe(Universe *uni, Camera *cam, int mode);
|
void render_universe(Universe *uni, Camera *cam, int mode);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,9 @@ Object3D *add_plane(Universe *uni, fixed x, fixed y, fixed z, fixed w, fixed d,
|
||||||
return obj;
|
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) {
|
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, SurfaceFunc func) {
|
||||||
int i, j, v_base;
|
int i, j, v_base;
|
||||||
Object3D *obj;
|
Object3D *obj;
|
||||||
fixed h_w = w / 2, h_d = d / 2;
|
fixed h_w = w / 2, h_d = d / 2;
|
||||||
|
|
@ -256,28 +258,22 @@ Object3D *add_math_surface(Universe *uni, fixed x, fixed y, fixed z, fixed w, fi
|
||||||
if (uni->num_verts + (seg_x + 1) * (seg_z + 1) > MAX_VERTEX) 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;
|
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;
|
obj = alloc_object(uni);
|
||||||
step_x = w / seg_x; step_z = d / seg_z;
|
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 (j = 0; j <= seg_z; j++) {
|
||||||
for (i = 0; i <= seg_x; i++) {
|
for (i = 0; i <= seg_x; i++) {
|
||||||
fixed vx = x - h_w + i * step_x;
|
fixed vx = x - h_w + i * step_x;
|
||||||
fixed vz = z - h_d + j * step_z;
|
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].x = vx;
|
||||||
uni->verts[uni->num_verts].y = y + (fixed)(fy * 65536.0);
|
/* Appel de la fonction passée en paramètre pour obtenir la hauteur */
|
||||||
|
uni->verts[uni->num_verts].y = y + func(vx, vz);
|
||||||
uni->verts[uni->num_verts].z = vz;
|
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].x = 0;
|
||||||
uni->v_normals[uni->num_verts].y = int_to_f(1);
|
uni->v_normals[uni->num_verts].y = int_to_f(1);
|
||||||
uni->v_normals[uni->num_verts].z = 0;
|
uni->v_normals[uni->num_verts].z = 0;
|
||||||
|
|
@ -285,7 +281,6 @@ Object3D *add_math_surface(Universe *uni, fixed x, fixed y, fixed z, fixed w, fi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Génération des faces (identique au plan) */
|
|
||||||
for (j = 0; j < seg_z; j++) {
|
for (j = 0; j < seg_z; j++) {
|
||||||
for (i = 0; i < seg_x; i++) {
|
for (i = 0; i < seg_x; i++) {
|
||||||
int a = v_base + j * (seg_x + 1) + i;
|
int a = v_base + j * (seg_x + 1) + i;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue