This commit is contained in:
Frater 2026-05-09 21:53:45 +02:00
commit eae91de89d
8 changed files with 641 additions and 280 deletions

View file

@ -1,112 +1,118 @@
#define GEOMETRY_H
#define MODE_WIRE 0 // Transparent total
#define MODE_HIDDEN 1 // Fil de fer avec surfaces cachées
#define MODE_SOLID 2  // Plein (Gouraud)
Point2D v_cache[5000];
#include "defines.h"
void add_face(Mesh *m, int a, int b, int c, uint8_t col, uint8_t wire) {
m->faces[m->num_faces++] = (Face){a, b, c, col, wire};
Face *f = &m->faces[m->num_faces++];
f->a = a;
f->b = b;
f->c = c;
f->color = col;
f->force_wire = wire;
}
void add_sphere(Mesh *m, fixed x, fixed y, fixed z, fixed r, int det, uint8_t col, uint8_t wire) {
int v_base = m->num_verts;
for (int j = 0; j <= det; j++) {
int i, j, v_base;
v_base = m->num_verts;
for (j = 0; j <= det; j++) {
fixed sin_phi = sintab[(j * 180 / det) % 360];
fixed cos_phi = costab[(j * 180 / det) % 360];
for (int i = 0; i < det; i++) {
for (i = 0; i < det; i++) {
Vector3 *v = &m->verts[m->num_verts];
Vector3 *n = &m->v_normals[m->num_verts];
fixed sin_th = sintab[(i * 360 / det) % 360];
fixed cos_th = costab[(i * 360 / det) % 360];
m->verts[m->num_verts] = (Vector3){x + f_mul(r, f_mul(sin_phi, cos_th)), y + f_mul(r, cos_phi), z + f_mul(r, f_mul(sin_phi, sin_th))};
m->v_normals[m->num_verts] = (Vector3){f_mul(sin_phi, cos_th), cos_phi, f_mul(sin_phi, sin_th)};
v->x = x + f_mul(r, f_mul(sin_phi, cos_th));
v->y = y + f_mul(r, cos_phi);
v->z = z + f_mul(r, f_mul(sin_phi, sin_th));
n->x = f_mul(sin_phi, cos_th);
n->y = cos_phi;
n->z = f_mul(sin_phi, sin_th);
m->num_verts++;
}
}
for (int j = 0; j < det; j++) {
for (int i = 0; i < det; i++) {
int a = v_base + j * det + i, b = v_base + j * det + (i + 1) % det;
int c = v_base + (j + 1) * det + i, d = v_base + (j + 1) * det + (i + 1) % det;
add_face(m, a, b, c, col, wire); add_face(m, b, d, c, col, wire);
for (j = 0; j < det; j++) {
for (i = 0; i < det; i++) {
int a = v_base + j * det + i;
int b = v_base + j * det + (i + 1) % det;
int c = v_base + (j + 1) * det + i;
int d = v_base + (j + 1) * det + (i + 1) % det;
add_face(m, a, b, c, col, wire);
add_face(m, b, d, c, col, wire);
}
}
}
void add_cylinder(Mesh *m, fixed x, fixed y, fixed z, fixed r, fixed h, int det, uint8_t col, uint8_t wire) {
int v_base = m->num_verts;
for (int i = 0; i < det; i++) {
fixed s = sintab[(i * 360 / det) % 360], c = costab[(i * 360 / det) % 360];
m->verts[m->num_verts] = (Vector3){x + f_mul(r, c), y - h / 2, z + f_mul(r, s)};
m->v_normals[m->num_verts] = (Vector3){c, 0, s}; m->num_verts++;
m->verts[m->num_verts] = (Vector3){x + f_mul(r, c), y + h / 2, z + f_mul(r, s)};
m->v_normals[m->num_verts] = (Vector3){c, 0, s}; m->num_verts++;
int i, v_base;
v_base = m->num_verts;
for (i = 0; i < det; i++) {
Vector3 *v1 = &m->verts[m->num_verts];
Vector3 *n1 = &m->v_normals[m->num_verts];
fixed s = sintab[(i * 360 / det) % 360];
fixed c = costab[(i * 360 / det) % 360];
v1->x = x + f_mul(r, c); v1->y = y - h / 2; v1->z = z + f_mul(r, s);
n1->x = c; n1->y = 0; n1->z = s;
m->num_verts++;
{ // Bloc pour v2/n2
Vector3 *v2 = &m->verts[m->num_verts];
Vector3 *n2 = &m->v_normals[m->num_verts];
v2->x = x + f_mul(r, c); v2->y = y + h / 2; v2->z = z + f_mul(r, s);
n2->x = c; n2->y = 0; n2->z = s;
m->num_verts++;
}
}
for (int i = 0; i < det; i++) {
int a = v_base + i * 2, b = v_base + ((i * 2 + 2) % (det * 2)), c = a + 1, d = b + 1;
add_face(m, a, b, c, col, wire); add_face(m, b, d, c, col, wire);
for (i = 0; i < det; i++) {
int a = v_base + i * 2;
int b = v_base + ((i * 2 + 2) % (det * 2));
int c = a + 1;
int d = b + 1;
add_face(m, a, b, c, col, wire);
add_face(m, b, d, c, col, wire);
}
}
void save_mesh(Mesh *m, const char *fn) {
FILE *f = fopen(fn, "wb"); 
fwrite(&m->num_verts, 4, 1, f); 
fwrite(&m->num_faces, 4, 1, f);
fwrite(m->verts, sizeof(Vector3), m->num_verts, f); 
fwrite(m->v_normals, sizeof(Vector3), m->num_verts, f);
fwrite(m->faces, sizeof(Face), m->num_faces, f); 
fclose(f);
FILE *f = fopen(fn, "wb");
if (!f) return;
fwrite(&m->num_verts, sizeof(int), 1, f);
fwrite(&m->num_faces, sizeof(int), 1, f);
fwrite(m->verts, sizeof(Vector3), m->num_verts, f);
fwrite(m->v_normals, sizeof(Vector3), m->num_verts, f);
fwrite(m->faces, sizeof(Face), m->num_faces, f);
fclose(f);
}
Mesh* load_mesh(const char *fname) {
FILE *f = fopen(fname, "rb");
if (!f) return NULL;
Mesh *m = (Mesh*)malloc(sizeof(Mesh));
fread(&m->num_verts, 4, 1, f);
fread(&m->num_faces, 4, 1, f);
fread(&m->is_wire_only, 1, 1, f);
m->verts = (Vector3*)malloc(sizeof(Vector3) * m->num_verts);
m->v_normals = (Vector3*)malloc(sizeof(Vector3) * m->num_verts);
m->faces = (Face*)malloc(sizeof(Face) * m->num_faces);
fread(m->verts, sizeof(Vector3), m->num_verts, f);
fread(m->v_normals, sizeof(Vector3), m->num_verts, f);
fread(m->faces, sizeof(Face), m->num_faces, f);
fclose(f);
return m;
Mesh *m;
FILE *f = fopen(fname, "rb");
if (!f) return NULL;
m = (Mesh*)malloc(sizeof(Mesh));
fread(&m->num_verts, sizeof(int), 1, f);
fread(&m->num_faces, sizeof(int), 1, f);
// Suppression de is_wire_only car absent du .h
m->verts = (Vector3*)malloc(sizeof(Vector3) * m->num_verts);
m->v_normals = (Vector3*)malloc(sizeof(Vector3) * m->num_verts);
m->faces = (Face*)malloc(sizeof(Face) * m->num_faces);
fread(m->verts, sizeof(Vector3), m->num_verts, f);
fread(m->v_normals, sizeof(Vector3), m->num_verts, f);
fread(m->faces, sizeof(Face), m->num_faces, f);
fclose(f);
return m;
}
void free_mesh(Mesh *m) {
if (!m) return;
if (m->verts) free(m->verts);
if (m->faces) free(m->faces);
if (m->v_normals) free(m->v_normals);
free(m);
}
void render_scene(Mesh *m, Matrix3 *rot, int global_mode) {
for (int i = 0; i < m->num_verts; i++) {
Vector3 *v = &m->verts[i]; Vector3 *n = &m->v_normals[i];
fixed nz = f_mul(n->x, rot->m[0][2]) + f_mul(n->y, rot->m[1][2]) + f_mul(n->z, rot->m[2][2]);
int intensity = f_to_int(nz * 15); if (intensity < 0) intensity = 0;
v_cache[i].z = v->z; v_cache[i].intensity = intensity;
v_cache[i].x = 160 + f_to_int(f_div(v->x << 8, v->z));
v_cache[i].y = 100 - f_to_int(f_div(v->y << 8, v->z));
}
for (int i = 0; i < m->num_faces; i++) {
Face *f = &m->faces[i]; Point2D *p1 = &v_cache[f->a], *p2 = &v_cache[f->b], *p3 = &v_cache[f->c];
int back = (p2->x - p1->x) * (p3->y - p1->y) - (p2->y - p1->y) * (p3->x - p1->x);
  
if (global_mode == MODE_WIRE) {
draw_line_z(p1, p2, f->color, 0); draw_line_z(p2, p3, f->color, 0); draw_line_z(p3, p1, f->color, 0);
} else {
if (back < 0) {
if (f->force_wire || global_mode == MODE_HIDDEN) {
fill_triangle_zonly(p1, p2, p3); // Pas de couleur, juste Z
draw_line_z(p1, p2, f->color, 1); draw_line_z(p2, p3, f->color, 1);
} else {
fill_triangle_gouraud(p1, p2, p3, f->color);
}
}
}
}
if (!m) return;
if (m->verts) free(m->verts);
if (m->faces) free(m->faces);
if (m->v_normals) free(m->v_normals);
free(m);
}