add parabole
This commit is contained in:
parent
2c525cb5e0
commit
a89bea929a
6 changed files with 447 additions and 32 deletions
112
src/main/main.c
112
src/main/main.c
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
Universe *uni;
|
Universe *uni;
|
||||||
Object3D *sph, *cyl, *tmp_obj;
|
Object3D *bus, *dish, *rtg_boom, *rtg1, *rtg2, *rtg3;
|
||||||
|
Object3D *mag_boom, *sci_boom, *cam_box, *record, *feed_boom, *sub_dish;
|
||||||
|
Object3D *tank, *pws1, *pws2, *inst1, *inst2;
|
||||||
Camera cam;
|
Camera cam;
|
||||||
Matrix3 rotX, rotY, orbit;
|
Matrix3 rotX, rotY, orbit;
|
||||||
|
Image *bg_img = NULL;
|
||||||
int special=0;
|
int special=0;
|
||||||
int anglex, angley, key, render, o;
|
int anglex, angley, key, render, o;
|
||||||
fixed bx, by, bz, distance;
|
fixed bx, by, bz, distance;
|
||||||
|
|
@ -20,36 +23,95 @@ int main(void) {
|
||||||
if (!uni) return 1;
|
if (!uni) return 1;
|
||||||
uni->num_verts = uni->num_faces = uni->num_objects = 0;
|
uni->num_verts = uni->num_faces = uni->num_objects = 0;
|
||||||
|
|
||||||
/* --- Ajout des objets : géométrie locale en (0,0,0) --- */
|
/* --- Construction de la sonde Voyager --- */
|
||||||
sph = add_sphere(uni, 0, 0, 0, int_to_f(30), 8, COLOR4, 0);
|
|
||||||
if (!sph) { free(uni); return 1; }
|
|
||||||
set_object_pos(sph,int_to_f(70),0,0);
|
|
||||||
//set_object_color(COLOR4);
|
|
||||||
|
|
||||||
cyl = add_cylinder(uni, 0, 0, 0, int_to_f(20), int_to_f(60), 12, COLOR2, 0);
|
/* 1. Bus principal (décagone blanc) */
|
||||||
if (!cyl) { free(uni); return 1; }
|
bus = add_cylinder(uni, 0, 0, 0, int_to_f(12), int_to_f(10), 10, COLOR7, 0);
|
||||||
set_object_pos(cyl,int_to_f(-70),0,0);
|
set_object_pos(bus, 0, 0, 0);
|
||||||
//set_object_color(COLOR2);
|
|
||||||
|
|
||||||
//tmp_obj = add_cone(uni, 0, 0, 0, int_to_f(20), int_to_f(60), 12, COLOR1, 0);
|
/* 1b. Réservoir d'hydrazine central (sphère dépassant sous le bus) */
|
||||||
tmp_obj = add_torus(uni, 0, 0, 0, int_to_f(20), int_to_f(10), 12, 12, COLOR1, 0);
|
tank = add_sphere(uni, 0, 0, 0, int_to_f(6), 8, COLOR7, 0);
|
||||||
|
set_object_pos(tank, 0, int_to_f(-3), 0);
|
||||||
|
|
||||||
|
/* 2a. Antenne parabolique (Paraboloïde avec courbure réaliste) */
|
||||||
|
dish = add_paraboloid(uni, 0, 0, 0, int_to_f(25), int_to_f(8), 24, 4, COLOR7, 0);
|
||||||
|
/* Pointant déjà vers le haut (+Y), on abaisse simplement sa base pour se reposer sur le bus */
|
||||||
|
set_object_pos(dish, 0, int_to_f(9), 0);
|
||||||
|
|
||||||
// tmp_obj = add_math_surface(uni, 0, 0, 0, int_to_f(120), int_to_f(120), 30, 30, COLOR2, 0);
|
/* 2b. Mât central de l'antenne (treillis triangulaire) */
|
||||||
// set_object_pos(tmp_obj, 0, int_to_f(-40), 0);
|
feed_boom = add_cylinder(uni, 0, 0, 0, int_to_f(1)/2, int_to_f(10), 3, COLOR7, 1);
|
||||||
|
set_object_pos(feed_boom, 0, int_to_f(10), 0);
|
||||||
|
|
||||||
|
/* 2c. Sous-réflecteur de l'antenne (petit cône inversé) */
|
||||||
|
sub_dish = add_cone(uni, 0, 0, 0, int_to_f(3), int_to_f(2), 12, COLOR7, 0);
|
||||||
|
bake_object_rotation(uni, sub_dish, 180, 0, 0);
|
||||||
|
set_object_pos(sub_dish, 0, int_to_f(16), 0);
|
||||||
|
|
||||||
/* Pour ajouter un troisième objet : */
|
/* 3. Mât du RTG (Générateur thermoélectrique, structure en treillis carrée) */
|
||||||
/*
|
rtg_boom = add_cylinder(uni, 0, 0, 0, int_to_f(2), int_to_f(40), 4, COLOR11, 1);
|
||||||
Object3D *sph2 = add_sphere(uni, 0, 0, 0, int_to_f(15), 6, COLOR6, 0);
|
bake_object_rotation(uni, rtg_boom, 0, 0, 90); /* Couché sur l'axe X */
|
||||||
sph2->base_pos.x = 0; sph2->base_pos.y = int_to_f(60); sph2->base_pos.z = 0;
|
set_object_pos(rtg_boom, int_to_f(25), int_to_f(-2), 0);
|
||||||
sph2->color = COLOR6;
|
|
||||||
*/
|
/* 4. RTG (Générateurs thermoélectriques, 3 segments en série) */
|
||||||
|
rtg1 = add_cylinder(uni, 0, 0, 0, int_to_f(4), int_to_f(5), 8, COLOR11, 0);
|
||||||
|
bake_object_rotation(uni, rtg1, 0, 0, 90);
|
||||||
|
set_object_pos(rtg1, int_to_f(48), int_to_f(-2), 0);
|
||||||
|
|
||||||
|
rtg2 = add_cylinder(uni, 0, 0, 0, int_to_f(4), int_to_f(5), 8, COLOR11, 0);
|
||||||
|
bake_object_rotation(uni, rtg2, 0, 0, 90);
|
||||||
|
set_object_pos(rtg2, int_to_f(54), int_to_f(-2), 0);
|
||||||
|
|
||||||
|
rtg3 = add_cylinder(uni, 0, 0, 0, int_to_f(4), int_to_f(5), 8, COLOR11, 0);
|
||||||
|
bake_object_rotation(uni, rtg3, 0, 0, 90);
|
||||||
|
set_object_pos(rtg3, int_to_f(60), int_to_f(-2), 0);
|
||||||
|
|
||||||
|
/* 5. Mât du magnétomètre (Très long, structure en treillis triangulaire) */
|
||||||
|
mag_boom = add_cylinder(uni, 0, 0, 0, int_to_f(1), int_to_f(70), 3, COLOR11, 1);
|
||||||
|
bake_object_rotation(uni, mag_boom, 0, 0, 90);
|
||||||
|
set_object_pos(mag_boom, int_to_f(-40), int_to_f(-2), 0);
|
||||||
|
|
||||||
|
/* 6. Mât de la plateforme scientifique (vers l'avant, axe Z, treillis carrée) */
|
||||||
|
sci_boom = add_cylinder(uni, 0, 0, 0, int_to_f(2), int_to_f(30), 4, COLOR11, 1);
|
||||||
|
bake_object_rotation(uni, sci_boom, 90, 0, 0); /* Couché sur l'axe Z */
|
||||||
|
set_object_pos(sci_boom, 0, int_to_f(-2), int_to_f(-20));
|
||||||
|
|
||||||
|
/* 7. Plateforme et caméras (cube gris) */
|
||||||
|
cam_box = add_box(uni, 0, 0, 0, int_to_f(6), int_to_f(6), int_to_f(6), COLOR11, 0);
|
||||||
|
set_object_pos(cam_box, 0, int_to_f(-2), int_to_f(-35));
|
||||||
|
|
||||||
|
/* 8. Le célèbre Golden Record ! (Petit cylindre jaune/or collé sur le flanc) */
|
||||||
|
record = add_cylinder(uni, 0, 0, 0, int_to_f(3), int_to_f(1), 10, COLOR4, 0);
|
||||||
|
bake_object_rotation(uni, record, 0, 0, 90);
|
||||||
|
set_object_pos(record, int_to_f(12), int_to_f(0), int_to_f(5));
|
||||||
|
|
||||||
|
/* 9. Antennes PWS (Plasma Wave Subsystem) - Longs tubes filaires en V */
|
||||||
|
pws1 = add_cylinder(uni, 0, 0, 0, int_to_f(1)/2, int_to_f(60), 3, COLOR11, 1);
|
||||||
|
bake_object_rotation(uni, pws1, 0, 0, 90); /* 1. On le couche sur l'axe X */
|
||||||
|
bake_object_rotation(uni, pws1, 0, 45, 0); /* 2. On l'écarte en V sur le plan XZ */
|
||||||
|
set_object_pos(pws1, int_to_f(-20), int_to_f(-5), int_to_f(20));
|
||||||
|
|
||||||
|
pws2 = add_cylinder(uni, 0, 0, 0, int_to_f(1)/2, int_to_f(60), 3, COLOR11, 1);
|
||||||
|
bake_object_rotation(uni, pws2, 0, 0, 90); /* 1. On le couche sur l'axe X */
|
||||||
|
bake_object_rotation(uni, pws2, 0, -45, 0);/* 2. On l'écarte en V sur le plan XZ */
|
||||||
|
set_object_pos(pws2, int_to_f(-20), int_to_f(-5), int_to_f(-20));
|
||||||
|
|
||||||
|
/* 10. Instruments optiques sur la plateforme scientifique (Télescopes/Caméras) */
|
||||||
|
inst1 = add_cylinder(uni, 0, 0, 0, int_to_f(2), int_to_f(8), 6, COLOR7, 0);
|
||||||
|
bake_object_rotation(uni, inst1, 90, 0, 0);
|
||||||
|
set_object_pos(inst1, int_to_f(-2), int_to_f(1), int_to_f(-38));
|
||||||
|
|
||||||
|
inst2 = add_cone(uni, 0, 0, 0, int_to_f(2), int_to_f(6), 8, COLOR7, 0);
|
||||||
|
bake_object_rotation(uni, inst2, 90, 0, 0);
|
||||||
|
set_object_pos(inst2, int_to_f(2), int_to_f(1), int_to_f(-38));
|
||||||
|
|
||||||
cam.pos.x = cam.pos.y = cam.pos.z = 0;
|
cam.pos.x = cam.pos.y = cam.pos.z = 0;
|
||||||
|
|
||||||
if (init_vga() != 0) { free(uni); return 1; }
|
if (init_vga() != 0) { free(uni); return 1; }
|
||||||
|
|
||||||
|
/* Optionnel : charger un fond (BMP 8-bit de 320x200 couleurs indexees) */
|
||||||
|
/* S'assurer que le fichier est bien généré avec les couleurs de votre palette moteur ! */
|
||||||
|
/* bg_img = load_bmp8("stars.bmp", NULL); */
|
||||||
|
|
||||||
while (key != 27) {
|
while (key != 27) {
|
||||||
if (kbhit()) {
|
if (kbhit()) {
|
||||||
special = 0;
|
special = 0;
|
||||||
|
|
@ -104,11 +166,19 @@ int main(void) {
|
||||||
obj->pos.z = distance + f_mul(bx, orbit.m[0][2]) + f_mul(by, orbit.m[1][2]) + f_mul(bz, orbit.m[2][2]);
|
obj->pos.z = distance + f_mul(bx, orbit.m[0][2]) + f_mul(by, orbit.m[1][2]) + f_mul(bz, orbit.m[2][2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_buffers(0);
|
if (bg_img) {
|
||||||
|
/* Dessiner le fond (qui écrase tout) et vider juste le Z-Buffer */
|
||||||
|
blit_image(bg_img, 0, 0);
|
||||||
|
clear_zbuffer();
|
||||||
|
} else {
|
||||||
|
clear_buffers(0);
|
||||||
|
}
|
||||||
|
|
||||||
render_universe(uni, &cam, render);
|
render_universe(uni, &cam, render);
|
||||||
flip();
|
flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bg_img) free_image(bg_img);
|
||||||
close_vga();
|
close_vga();
|
||||||
free(uni);
|
free(uni);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,12 @@ typedef struct { fixed x, y, z; } Vector3;
|
||||||
typedef struct { int a, b, c; uint8_t force_wire; } Face;
|
typedef struct { int a, b, c; uint8_t force_wire; } Face;
|
||||||
typedef struct { int x, y; fixed z; fixed intensity; } Point2D;
|
typedef struct { int x, y; fixed z; fixed intensity; } Point2D;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
uint8_t *data;
|
||||||
|
} Image;
|
||||||
|
|
||||||
/* Un objet dans l'univers : tranche du pool partagé + transform */
|
/* Un objet dans l'univers : tranche du pool partagé + transform */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int vert_start, num_verts; /* indices dans Universe.verts/v_normals */
|
int vert_start, num_verts; /* indices dans Universe.verts/v_normals */
|
||||||
|
|
@ -117,6 +123,7 @@ 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_paraboloid(Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, int det, int rings, 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,
|
Object3D* add_math_surface(Universe *uni, fixed x, fixed y, fixed z,
|
||||||
fixed w, fixed d, int seg_x, int seg_z,
|
fixed w, fixed d, int seg_x, int seg_z,
|
||||||
|
|
@ -126,6 +133,10 @@ void render_universe(Universe *uni, Camera *cam, int mode);
|
||||||
|
|
||||||
int init_vga(void);
|
int init_vga(void);
|
||||||
void clear_buffers(uint8_t color);
|
void clear_buffers(uint8_t color);
|
||||||
|
void clear_zbuffer(void);
|
||||||
|
void blit_image(Image *img, int x, int y);
|
||||||
|
void blit_image_transparent(Image *img, int x, int y, uint8_t color_key);
|
||||||
|
void apply_256_palette(RGB *pal);
|
||||||
void flip(void);
|
void flip(void);
|
||||||
void close_vga(void);
|
void close_vga(void);
|
||||||
|
|
||||||
|
|
@ -136,4 +147,8 @@ void save_mesh(Mesh *m, const char *fn);
|
||||||
Mesh *load_mesh(const char *fname);
|
Mesh *load_mesh(const char *fname);
|
||||||
void free_mesh(Mesh *m);
|
void free_mesh(Mesh *m);
|
||||||
|
|
||||||
|
Image *create_image(int width, int height);
|
||||||
|
void free_image(Image *img);
|
||||||
|
Image *load_bmp8(const char *filename, RGB *pal_out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ void mat3_rotate_z(Matrix3 *m, int angle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fait pivoter la géométrie locale de l'objet de façon permanente */
|
/* 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) {
|
void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az) {
|
||||||
Matrix3 rx, ry, rz, tmp, rot;
|
Matrix3 rx, ry, rz, tmp, rot;
|
||||||
Vector3 *v, *n;
|
Vector3 *v, *n;
|
||||||
|
|
@ -70,20 +71,20 @@ void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az)
|
||||||
|
|
||||||
if (!obj || !uni) return;
|
if (!obj || !uni) return;
|
||||||
|
|
||||||
/* Composition de la matrice de rotation */
|
/* Composition de la matrice de rotation * /
|
||||||
mat3_rotate_x(&rx, ax);
|
mat3_rotate_x(&rx, ax);
|
||||||
mat3_rotate_y(&ry, ay);
|
mat3_rotate_y(&ry, ay);
|
||||||
mat3_rotate_z(&rz, az);
|
mat3_rotate_z(&rz, az);
|
||||||
mat3_mul(&tmp, &rx, &ry);
|
mat3_mul(&tmp, &rx, &ry);
|
||||||
mat3_mul(&rot, &tmp, &rz);
|
mat3_mul(&rot, &tmp, &rz);
|
||||||
|
|
||||||
/* Application à tous les sommets et normales de l'objet */
|
/* Application à tous les sommets et normales de l'objet * /
|
||||||
for (i = 0; i < obj->num_verts; i++) {
|
for (i = 0; i < obj->num_verts; i++) {
|
||||||
vi = obj->vert_start + i;
|
vi = obj->vert_start + i;
|
||||||
v = &uni->verts[vi];
|
v = &uni->verts[vi];
|
||||||
n = &uni->v_normals[vi];
|
n = &uni->v_normals[vi];
|
||||||
|
|
||||||
/* Sommets */
|
/* 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]);
|
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]);
|
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]);
|
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]);
|
||||||
|
|
@ -91,7 +92,7 @@ void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az)
|
||||||
v->y = vy;
|
v->y = vy;
|
||||||
v->z = vz;
|
v->z = vz;
|
||||||
|
|
||||||
/* Normales (doivent aussi pivoter pour l'ombrage Gouraud !) */
|
/* 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]);
|
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]);
|
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]);
|
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]);
|
||||||
|
|
@ -100,7 +101,7 @@ void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az)
|
||||||
n->z = vz;
|
n->z = vz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
void render_universe(Universe *uni, Camera *cam, int mode) {
|
void render_universe(Universe *uni, Camera *cam, int mode) {
|
||||||
int o, i, vi, front;
|
int o, i, vi, front;
|
||||||
fixed rx, ry, rz, pz, nz;
|
fixed rx, ry, rz, pz, nz;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,68 @@ void set_object_color(Object3D *obj, uint8_t col) {
|
||||||
obj->color = col;
|
obj->color = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Rotation permanente (baking) de la géométrie locale de l'objet */
|
||||||
|
void bake_object_rotation(Universe *uni, Object3D *obj, int ax, int ay, int az) {
|
||||||
|
int i;
|
||||||
|
fixed cx, sx, cy, sy, cz, sz;
|
||||||
|
fixed x, y, z, tx, ty, tz;
|
||||||
|
Vector3 *v, *n;
|
||||||
|
|
||||||
|
if (!uni || !obj) return;
|
||||||
|
|
||||||
|
/* Normalisation des angles (0-359) */
|
||||||
|
ax = ((ax % 360) + 360) % 360;
|
||||||
|
ay = ((ay % 360) + 360) % 360;
|
||||||
|
az = ((az % 360) + 360) % 360;
|
||||||
|
|
||||||
|
cx = costab[ax]; sx = sintab[ax];
|
||||||
|
cy = costab[ay]; sy = sintab[ay];
|
||||||
|
cz = costab[az]; sz = sintab[az];
|
||||||
|
|
||||||
|
for (i = 0; i < obj->num_verts; i++) {
|
||||||
|
v = &uni->verts[obj->vert_start + i];
|
||||||
|
n = &uni->v_normals[obj->vert_start + i];
|
||||||
|
|
||||||
|
/* --- Transformation du Sommet --- */
|
||||||
|
x = v->x; y = v->y; z = v->z;
|
||||||
|
if (ax) {
|
||||||
|
ty = f_mul(y, cx) - f_mul(z, sx);
|
||||||
|
tz = f_mul(y, sx) + f_mul(z, cx);
|
||||||
|
y = ty; z = tz;
|
||||||
|
}
|
||||||
|
if (ay) {
|
||||||
|
tx = f_mul(x, cy) + f_mul(z, sy);
|
||||||
|
tz = -f_mul(x, sy) + f_mul(z, cy);
|
||||||
|
x = tx; z = tz;
|
||||||
|
}
|
||||||
|
if (az) {
|
||||||
|
tx = f_mul(x, cz) - f_mul(y, sz);
|
||||||
|
ty = f_mul(x, sz) + f_mul(y, cz);
|
||||||
|
x = tx; y = ty;
|
||||||
|
}
|
||||||
|
v->x = x; v->y = y; v->z = z;
|
||||||
|
|
||||||
|
/* --- Transformation de la Normale --- */
|
||||||
|
x = n->x; y = n->y; z = n->z;
|
||||||
|
if (ax) {
|
||||||
|
ty = f_mul(y, cx) - f_mul(z, sx);
|
||||||
|
tz = f_mul(y, sx) + f_mul(z, cx);
|
||||||
|
y = ty; z = tz;
|
||||||
|
}
|
||||||
|
if (ay) {
|
||||||
|
tx = f_mul(x, cy) + f_mul(z, sy);
|
||||||
|
tz = -f_mul(x, sy) + f_mul(z, cy);
|
||||||
|
x = tx; z = tz;
|
||||||
|
}
|
||||||
|
if (az) {
|
||||||
|
tx = f_mul(x, cz) - f_mul(y, sz);
|
||||||
|
ty = f_mul(x, sz) + f_mul(y, cz);
|
||||||
|
x = tx; y = ty;
|
||||||
|
}
|
||||||
|
n->x = x; n->y = y; n->z = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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_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;
|
int i, j, v_base;
|
||||||
Object3D *obj;
|
Object3D *obj;
|
||||||
|
|
@ -232,6 +294,115 @@ Object3D *add_cone(Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, i
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object3D *add_paraboloid(Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, int det, int rings, uint8_t col, uint8_t wire) {
|
||||||
|
int i, j, v_base_in, v_base_out;
|
||||||
|
int th, r_cur, r_next, a, b, c, d;
|
||||||
|
double t, rad, height, dy_dr, nx_base, ny_base, len, angle;
|
||||||
|
Object3D *obj;
|
||||||
|
fixed half_h = h / 2;
|
||||||
|
|
||||||
|
if (uni->num_objects >= MAX_OBJECTS) return NULL;
|
||||||
|
if (uni->num_verts + 2 * (1 + rings * det) > MAX_VERTEX) return NULL;
|
||||||
|
if (uni->num_faces + 2 * (det + (rings - 1) * det * 2) > MAX_FACES) return NULL;
|
||||||
|
|
||||||
|
obj = alloc_object(uni);
|
||||||
|
obj->color = col;
|
||||||
|
|
||||||
|
/* --- FACE INTERIEURE (Bol de l'antenne, normale vers l'avant +Y) --- */
|
||||||
|
v_base_in = 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++;
|
||||||
|
|
||||||
|
for (i = 1; i <= rings; i++) {
|
||||||
|
t = (double)i / rings;
|
||||||
|
rad = ((double)r / 65536.0) * t;
|
||||||
|
height = ((double)h / 65536.0) * (t * t); /* Courbe y = x^2 */
|
||||||
|
dy_dr = 2.0 * ((double)h / 65536.0) * t / ((double)r / 65536.0); /* Dérivée */
|
||||||
|
nx_base = -dy_dr;
|
||||||
|
ny_base = 1.0;
|
||||||
|
len = sqrt(nx_base * nx_base + ny_base * ny_base);
|
||||||
|
nx_base /= len; ny_base /= len;
|
||||||
|
|
||||||
|
for (j = 0; j < det; j++) {
|
||||||
|
th = (j * 360 / det) % 360;
|
||||||
|
angle = th * 3.14159265 / 180.0;
|
||||||
|
uni->v_normals[uni->num_verts].x = (fixed)(nx_base * cos(angle) * 65536.0);
|
||||||
|
uni->v_normals[uni->num_verts].y = (fixed)(ny_base * 65536.0);
|
||||||
|
uni->v_normals[uni->num_verts].z = (fixed)(nx_base * sin(angle) * 65536.0);
|
||||||
|
uni->verts[uni->num_verts].x = x + (fixed)(rad * cos(angle) * 65536.0);
|
||||||
|
uni->verts[uni->num_verts].y = y - half_h + (fixed)(height * 65536.0);
|
||||||
|
uni->verts[uni->num_verts].z = z + (fixed)(rad * sin(angle) * 65536.0);
|
||||||
|
uni->num_verts++; obj->num_verts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (j = 0; j < det; j++) {
|
||||||
|
push_face(uni, obj, v_base_in, v_base_in + 1 + ((j + 1) % det), v_base_in + 1 + j, wire);
|
||||||
|
}
|
||||||
|
for (i = 1; i < rings; i++) {
|
||||||
|
r_cur = v_base_in + 1 + (i - 1) * det;
|
||||||
|
r_next = v_base_in + 1 + i * det;
|
||||||
|
for (j = 0; j < det; j++) {
|
||||||
|
a = r_cur + j;
|
||||||
|
b = r_cur + ((j + 1) % det);
|
||||||
|
c = r_next + j;
|
||||||
|
d = r_next + ((j + 1) % det);
|
||||||
|
push_face(uni, obj, a, b, c, wire);
|
||||||
|
push_face(uni, obj, b, d, c, wire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- FACE EXTERIEURE (Dos de l'antenne, normale vers l'arrière -Y) --- */
|
||||||
|
v_base_out = 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++;
|
||||||
|
|
||||||
|
for (i = 1; i <= rings; i++) {
|
||||||
|
t = (double)i / rings;
|
||||||
|
rad = ((double)r / 65536.0) * t;
|
||||||
|
height = ((double)h / 65536.0) * (t * t);
|
||||||
|
dy_dr = 2.0 * ((double)h / 65536.0) * t / ((double)r / 65536.0);
|
||||||
|
nx_base = dy_dr; /* Normale inversée */
|
||||||
|
ny_base = -1.0;
|
||||||
|
len = sqrt(nx_base * nx_base + ny_base * ny_base);
|
||||||
|
nx_base /= len; ny_base /= len;
|
||||||
|
|
||||||
|
for (j = 0; j < det; j++) {
|
||||||
|
th = (j * 360 / det) % 360;
|
||||||
|
angle = th * 3.14159265 / 180.0;
|
||||||
|
uni->v_normals[uni->num_verts].x = (fixed)(nx_base * cos(angle) * 65536.0);
|
||||||
|
uni->v_normals[uni->num_verts].y = (fixed)(ny_base * 65536.0);
|
||||||
|
uni->v_normals[uni->num_verts].z = (fixed)(nx_base * sin(angle) * 65536.0);
|
||||||
|
uni->verts[uni->num_verts].x = x + (fixed)(rad * cos(angle) * 65536.0);
|
||||||
|
uni->verts[uni->num_verts].y = y - half_h + (fixed)(height * 65536.0);
|
||||||
|
uni->verts[uni->num_verts].z = z + (fixed)(rad * sin(angle) * 65536.0);
|
||||||
|
uni->num_verts++; obj->num_verts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (j = 0; j < det; j++) {
|
||||||
|
push_face(uni, obj, v_base_out, v_base_out + 1 + j, v_base_out + 1 + ((j + 1) % det), wire); /* Winding inversé */
|
||||||
|
}
|
||||||
|
for (i = 1; i < rings; i++) {
|
||||||
|
r_cur = v_base_out + 1 + (i - 1) * det;
|
||||||
|
r_next = v_base_out + 1 + i * det;
|
||||||
|
for (j = 0; j < det; j++) {
|
||||||
|
a = r_cur + j; b = r_cur + ((j + 1) % det); c = r_next + j; d = r_next + ((j + 1) % det);
|
||||||
|
push_face(uni, obj, a, c, b, wire); /* Winding inversé */
|
||||||
|
push_face(uni, obj, b, c, d, 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) {
|
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;
|
int i, j, v_base;
|
||||||
Object3D *obj;
|
Object3D *obj;
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,80 @@ void clear_buffers(uint8_t color) {
|
||||||
memset(zbuffer, 0xFF, SCREEN_PIXELS * sizeof(uint16_t));
|
memset(zbuffer, 0xFF, SCREEN_PIXELS * sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear_zbuffer(void) {
|
||||||
|
memset(zbuffer, 0xFF, SCREEN_PIXELS * sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void blit_image(Image *img, int x, int y) {
|
||||||
|
int j;
|
||||||
|
int sx, sy, dx, dy, w, h;
|
||||||
|
uint8_t *src, *dst;
|
||||||
|
|
||||||
|
if (!img || !img->data || !backbuffer) return;
|
||||||
|
|
||||||
|
sx = 0; sy = 0;
|
||||||
|
dx = x; dy = y;
|
||||||
|
w = img->width; h = img->height;
|
||||||
|
|
||||||
|
if (dx < 0) { sx = -dx; w += dx; dx = 0; }
|
||||||
|
if (dy < 0) { sy = -dy; h += dy; dy = 0; }
|
||||||
|
if (dx + w > SCREEN_W) w = SCREEN_W - dx;
|
||||||
|
if (dy + h > SCREEN_H) h = SCREEN_H - dy;
|
||||||
|
|
||||||
|
if (w <= 0 || h <= 0) return;
|
||||||
|
|
||||||
|
src = img->data + sy * img->width + sx;
|
||||||
|
dst = backbuffer + dy * SCREEN_W + dx;
|
||||||
|
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
memcpy(dst, src, w);
|
||||||
|
src += img->width;
|
||||||
|
dst += SCREEN_W;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void blit_image_transparent(Image *img, int x, int y, uint8_t color_key) {
|
||||||
|
int i, j;
|
||||||
|
int sx, sy, dx, dy, w, h;
|
||||||
|
uint8_t *src, *dst;
|
||||||
|
|
||||||
|
if (!img || !img->data || !backbuffer) return;
|
||||||
|
|
||||||
|
sx = 0; sy = 0;
|
||||||
|
dx = x; dy = y;
|
||||||
|
w = img->width; h = img->height;
|
||||||
|
|
||||||
|
if (dx < 0) { sx = -dx; w += dx; dx = 0; }
|
||||||
|
if (dy < 0) { sy = -dy; h += dy; dy = 0; }
|
||||||
|
if (dx + w > SCREEN_W) w = SCREEN_W - dx;
|
||||||
|
if (dy + h > SCREEN_H) h = SCREEN_H - dy;
|
||||||
|
|
||||||
|
if (w <= 0 || h <= 0) return;
|
||||||
|
|
||||||
|
src = img->data + sy * img->width + sx;
|
||||||
|
dst = backbuffer + dy * SCREEN_W + dx;
|
||||||
|
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
for (i = 0; i < w; i++) {
|
||||||
|
if (src[i] != color_key) {
|
||||||
|
dst[i] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
src += img->width;
|
||||||
|
dst += SCREEN_W;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_256_palette(RGB *pal) {
|
||||||
|
int i;
|
||||||
|
outp(0x3C8, 0);
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
outp(0x3C9, pal[i].r);
|
||||||
|
outp(0x3C9, pal[i].g);
|
||||||
|
outp(0x3C9, pal[i].b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void flip(void) {
|
void flip(void) {
|
||||||
memcpy(vga, backbuffer, SCREEN_PIXELS);
|
memcpy(vga, backbuffer, SCREEN_PIXELS);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
84
src/part3D/image.c
Normal file
84
src/part3D/image.c
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
Image *create_image(int width, int height) {
|
||||||
|
Image *img = (Image *)malloc(sizeof(Image));
|
||||||
|
if (!img) return NULL;
|
||||||
|
img->width = width;
|
||||||
|
img->height = height;
|
||||||
|
img->data = (uint8_t *)malloc(width * height);
|
||||||
|
if (!img->data) {
|
||||||
|
free(img);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_image(Image *img) {
|
||||||
|
if (img) {
|
||||||
|
if (img->data) free(img->data);
|
||||||
|
free(img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image *load_bmp8(const char *filename, RGB *pal_out) {
|
||||||
|
FILE *f;
|
||||||
|
uint8_t header[54];
|
||||||
|
uint32_t data_offset, header_size, width, height;
|
||||||
|
int32_t h32;
|
||||||
|
uint16_t bpp;
|
||||||
|
int is_top_down = 0;
|
||||||
|
Image *img;
|
||||||
|
int i, y;
|
||||||
|
uint8_t pal_buf[1024];
|
||||||
|
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
if (!f) return NULL;
|
||||||
|
|
||||||
|
if (fread(header, 1, 54, f) != 54) { fclose(f); return NULL; }
|
||||||
|
if (header[0] != 'B' || header[1] != 'M') { fclose(f); return NULL; }
|
||||||
|
|
||||||
|
/* Lecture sécurisée (évite les soucis d'alignement mémoire x86) */
|
||||||
|
data_offset = header[10] | (header[11] << 8) | (header[12] << 16) | (header[13] << 24);
|
||||||
|
header_size = header[14] | (header[15] << 8) | (header[16] << 16) | (header[17] << 24);
|
||||||
|
width = header[18] | (header[19] << 8) | (header[20] << 16) | (header[21] << 24);
|
||||||
|
h32 = header[22] | (header[23] << 8) | (header[24] << 16) | (header[25] << 24);
|
||||||
|
bpp = header[28] | (header[29] << 8);
|
||||||
|
|
||||||
|
if (h32 < 0) { is_top_down = 1; height = -h32; }
|
||||||
|
else { height = h32; }
|
||||||
|
|
||||||
|
if (bpp != 8) { fclose(f); return NULL; }
|
||||||
|
|
||||||
|
img = create_image(width, height);
|
||||||
|
if (!img) { fclose(f); return NULL; }
|
||||||
|
|
||||||
|
if (pal_out) {
|
||||||
|
fseek(f, 14 + header_size, SEEK_SET);
|
||||||
|
fread(pal_buf, 1, 1024, f);
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
/* Le DAC VGA s'attend à des valeurs de 0 à 63 (>> 2) */
|
||||||
|
pal_out[i].b = pal_buf[i*4] >> 2;
|
||||||
|
pal_out[i].g = pal_buf[i*4+1] >> 2;
|
||||||
|
pal_out[i].r = pal_buf[i*4+2] >> 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(f, data_offset, SEEK_SET);
|
||||||
|
|
||||||
|
/* Les scanlines d'un BMP sont alignées sur des multiples de 4 octets */
|
||||||
|
{
|
||||||
|
int row_padded = (width + 3) & (~3);
|
||||||
|
uint8_t *row_data = (uint8_t *)malloc(row_padded);
|
||||||
|
if (row_data) {
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
y = is_top_down ? i : (height - 1 - i);
|
||||||
|
fread(row_data, 1, row_padded, f);
|
||||||
|
memcpy(&img->data[y * width], row_data, width);
|
||||||
|
}
|
||||||
|
free(row_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return img;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue