diff --git a/README.md b/README.md index a232bc0..ab28572 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Moteur 3D DOS (TESTING) +**Version : 0.15** + ## Vue d'ensemble Moteur 3D software en C ciblant le DOS 32-bit via l'extender **CauseWay** (ou DOS/4GW). diff --git a/WORKDOC.md b/WORKDOC.md index 39f880f..c36d7a8 100644 --- a/WORKDOC.md +++ b/WORKDOC.md @@ -1,5 +1,7 @@ # Moteur 3D DOS (TESTING) +**Version : 0.15** + ## Vue d'ensemble Moteur 3D software en C ciblant le DOS 32-bit via l'extender **CauseWay** (ou DOS/4GW). diff --git a/src/main/main.c b/src/main/main.c index 00125fb..1a65ca7 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -12,6 +12,11 @@ int main(void) { int anglex, angley, key, render, o; fixed bx, by, bz, distance; + printf("Moteur 3D DOS (TESTING) - Version 0.15\n"); + printf("Compile le %s a %s\n\n", __DATE__, __TIME__); + printf("Appuyez sur une touche pour demarrer le rendu...\n"); + getch(); + anglex = angley = key = 0; render = MODE_SOLID; distance = int_to_f(300); @@ -122,7 +127,9 @@ int main(void) { switch (key) { case 59: render = MODE_WIRE; break; /* F1 */ case 60: render = MODE_HIDDEN; break; /* F2 */ - case 61: render = MODE_SOLID; break; /* F3 */ + case 61: render = MODE_FLAT; break; /* F3 */ + case 62: render = MODE_FLAT_SHADING; break; /* F4 */ + case 63: render = MODE_SOLID; break; /* F5 */ case 71: distance -= int_to_f(10); break; /* Home : Rapprocher le centre */ case 79: distance += int_to_f(10); break; /* End : Eloigner le centre */ case 72: anglex = ((anglex - 3) % 360 + 360) % 360; break; /* Flèche Haut */ diff --git a/src/part3D/defines.h b/src/part3D/defines.h index 9bb0d30..3aaead5 100644 --- a/src/part3D/defines.h +++ b/src/part3D/defines.h @@ -14,7 +14,9 @@ #define MODE_WIRE 0 #define MODE_HIDDEN 1 -#define MODE_SOLID 2 +#define MODE_FLAT 2 +#define MODE_FLAT_SHADING 3 +#define MODE_SOLID 4 #define SCREEN_W 320 #define SCREEN_H 200 @@ -141,6 +143,7 @@ void flip(void); void close_vga(void); void fill_triangle_gouraud(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t base_color); +void fill_triangle_flat(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t color); void draw_line_z(Point2D *p1, Point2D *p2, uint8_t col, int z_test); void save_mesh(Mesh *m, const char *fn); diff --git a/src/part3D/engine.c b/src/part3D/engine.c index a163938..1a66179 100644 --- a/src/part3D/engine.c +++ b/src/part3D/engine.c @@ -110,6 +110,9 @@ void render_universe(Universe *uni, Camera *cam, int mode) { Object3D *obj; Face *f; Point2D *p1, *p2, *p3; + fixed avg_i; + int s; + uint8_t shade; for (o = 0; o < uni->num_objects; o++) { obj = &uni->objects[o]; @@ -156,6 +159,33 @@ void render_universe(Universe *uni, Camera *cam, int mode) { draw_line_z(p3, p1, wire_col, 1); } break; + case MODE_FLAT: + if (front) { + if (f->force_wire) { + draw_line_z(p1, p2, wire_col, 1); + draw_line_z(p2, p3, wire_col, 1); + draw_line_z(p3, p1, wire_col, 1); + } else { + fill_triangle_flat(p1, p2, p3, wire_col); + } + } + break; + case MODE_FLAT_SHADING: + if (front) { + if (f->force_wire) { + draw_line_z(p1, p2, wire_col, 1); + draw_line_z(p2, p3, wire_col, 1); + draw_line_z(p3, p1, wire_col, 1); + } else { + avg_i = (p1->intensity + p2->intensity + p3->intensity) / 3; + s = f_to_int(avg_i); + if (s < 0) shade = 0; + else if (s > 15) shade = 15; + else shade = (uint8_t)s; + fill_triangle_flat(p1, p2, p3, (uint8_t)((obj->color << 4) | shade)); + } + } + break; case MODE_SOLID: default: if (front) { diff --git a/src/part3D/raster.c b/src/part3D/raster.c index 5057483..5156fa7 100644 --- a/src/part3D/raster.c +++ b/src/part3D/raster.c @@ -117,6 +117,99 @@ void fill_triangle_gouraud(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t base_c } } +/* Rendu d'une scanline avec z-buffer (couleur unie) */ +void scanline_flat_c(int width, uint8_t *dest, uint16_t *zbuf, + fixed z, fixed dz_step, uint8_t color) { + int i; + uint16_t zv; + + for (i = 0; i < width; i++) { + zv = (uint16_t)(z >> 16); + if (zv < zbuf[i]) { + zbuf[i] = zv; + dest[i] = color; + } + z += dz_step; + } +} + +void fill_triangle_flat(Point2D *p1, Point2D *p2, Point2D *p3, uint8_t color) { + int y, width, start_x, end_x, clip_x, w, second_half, total_height; + fixed dx13, dz13, xA, zA, xB, zB, dx12, dz12, dx23, dz23; + fixed cx1, cz1, cx2, cz2, tx, tz; + fixed dz_step, start_z; + uint8_t *dest; + uint16_t *zbuf; + + /* Tri des points par ordonnée (Y) */ + if (p1->y > p2->y) swap_pt(&p1, &p2); + if (p1->y > p3->y) swap_pt(&p1, &p3); + if (p2->y > p3->y) swap_pt(&p2, &p3); + + total_height = p3->y - p1->y; + if (total_height == 0) return; + + /* Gradients pour le côté long (p1 vers p3) */ + dx13 = ((p3->x - p1->x) << 16) / total_height; + dz13 = (p3->z - p1->z) / total_height; + + xA = int_to_f(p1->x); zA = p1->z; + if (p1->y == p2->y) { + xB = int_to_f(p2->x); zB = p2->z; + } else { + xB = xA; zB = zA; + } + + /* Gradients pour les côtés courts */ + dx12 = (p2->y > p1->y) ? ((p2->x - p1->x) << 16) / (p2->y - p1->y) : 0; + dz12 = (p2->y > p1->y) ? (p2->z - p1->z) / (p2->y - p1->y) : 0; + + dx23 = (p3->y > p2->y) ? ((p3->x - p2->x) << 16) / (p3->y - p2->y) : 0; + dz23 = (p3->y > p2->y) ? (p3->z - p2->z) / (p3->y - p2->y) : 0; + + for (y = p1->y; y < p3->y; y++) { + second_half = (y >= p2->y); + cx1 = xA; cz1 = zA; + cx2 = xB; cz2 = zB; + + /* Tri horizontal */ + if (cx1 > cx2) { + tx = cx1; cx1 = cx2; cx2 = tx; + tz = cz1; cz1 = cz2; cz2 = tz; + } + + start_x = f_to_int(cx1); + end_x = f_to_int(cx2) + 1; + width = end_x - start_x; + + if (y >= 0 && y < SCREEN_H && width > 0) { + dz_step = (cz2 - cz1) / width; + + clip_x = (start_x < 0) ? 0 : start_x; + w = width - (clip_x - start_x); + if (clip_x + w > SCREEN_W) w = SCREEN_W - clip_x; + + if (w > 0) { + start_z = cz1 + (clip_x - start_x) * dz_step; + dest = backbuffer + (y * SCREEN_W) + clip_x; + zbuf = zbuffer + (y * SCREEN_W) + clip_x; + + scanline_flat_c(w, dest, zbuf, start_z, dz_step, color); + } + } + + xA += dx13; zA += dz13; + if (!second_half) { + xB += dx12; zB += dz12; + } else { + if (y == p2->y) { + xB = int_to_f(p2->x); zB = p2->z; + } + xB += dx23; zB += dz23; + } + } +} + void draw_line_z(Point2D *p1, Point2D *p2, uint8_t col, int z_test) { int dx, dy, sx, sy, err, steps, x, y, e2; fixed z_step, cz;