#include "defines.h" static void push_face(Universe *uni, Object3D *obj, int a, int b, int c, uint8_t wire) { Face *f = &uni->faces[uni->num_faces++]; f->a = a; f->b = b; f->c = c; f->force_wire = wire; obj->num_faces++; } static Object3D *alloc_object(Universe *uni) { Object3D *obj = &uni->objects[uni->num_objects++]; obj->vert_start = uni->num_verts; obj->face_start = uni->num_faces; obj->num_verts = 0; obj->num_faces = 0; obj->pos.x = obj->pos.y = obj->pos.z = 0; obj->base_pos.x = obj->base_pos.y = obj->base_pos.z = 0; mat3_identity(&obj->rot); return obj; } Object3D *add_sphere(Universe *uni, fixed x, fixed y, fixed z, fixed r, int det, uint8_t col, uint8_t wire) { int i, j, v_base, phi, th; Object3D *obj; Vector3 *v, *n; if (uni->num_objects >= MAX_OBJECTS) return NULL; if (uni->num_verts + (det + 1) * det > MAX_VERTEX) return NULL; if (uni->num_faces + det * det * 2 > MAX_FACES) return NULL; obj = alloc_object(uni); obj->color = col; v_base = uni->num_verts; for (j = 0; j <= det; j++) { phi = (j * 180 / det) % 360; for (i = 0; i < det; i++) { th = (i * 360 / det) % 360; v = &uni->verts[uni->num_verts]; n = &uni->v_normals[uni->num_verts]; n->x = f_mul(sintab[phi], costab[th]); n->y = costab[phi]; n->z = f_mul(sintab[phi], sintab[th]); v->x = x + f_mul(r, n->x); v->y = y + f_mul(r, n->y); v->z = z + f_mul(r, n->z); uni->num_verts++; obj->num_verts++; } } 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; push_face(uni, obj, a, b, c, wire); push_face(uni, obj, b, d, c, wire); } } return obj; } Object3D *add_cylinder(Universe *uni, fixed x, fixed y, fixed z, fixed r, fixed h, int det, uint8_t col, uint8_t wire) { int i, v_base, cap_bot_center, cap_bot_rim, cap_top_center, cap_top_rim, th; fixed half_h, s, cs; Object3D *obj; if (uni->num_objects >= MAX_OBJECTS) return NULL; if (uni->num_verts + 2 + 4 * det > MAX_VERTEX) return NULL; if (uni->num_faces + 4 * det > MAX_FACES) return NULL; obj = alloc_object(uni); obj->color = col; v_base = uni->num_verts; half_h = h / 2; /* --- Corps --- */ for (i = 0; i < det; i++) { th = (i * 360 / det) % 360; s = sintab[th]; cs = costab[th]; uni->v_normals[uni->num_verts].x = cs; uni->v_normals[uni->num_verts].y = 0; uni->v_normals[uni->num_verts].z = s; uni->verts[uni->num_verts].x = x + f_mul(r, cs); uni->verts[uni->num_verts].y = y - half_h; uni->verts[uni->num_verts].z = z + f_mul(r, s); uni->num_verts++; obj->num_verts++; uni->v_normals[uni->num_verts].x = cs; uni->v_normals[uni->num_verts].y = 0; uni->v_normals[uni->num_verts].z = s; uni->verts[uni->num_verts].x = x + f_mul(r, cs); uni->verts[uni->num_verts].y = y + half_h; uni->verts[uni->num_verts].z = z + f_mul(r, s); uni->num_verts++; obj->num_verts++; } for (i = 0; i < det; i++) { int a = v_base + (i * 2); int b = v_base + ((i * 2 + 2) % (det * 2)); int cv = a + 1; int d = b + 1; push_face(uni, obj, a, cv, b, wire); push_face(uni, obj, cv, d, b, wire); } /* --- Fond bas --- */ cap_bot_center = 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++; cap_bot_rim = uni->num_verts; for (i = 0; i < det; i++) { th = (i * 360 / det) % 360; s = sintab[th]; cs = costab[th]; 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 + f_mul(r, cs); uni->verts[uni->num_verts].y = y - half_h; uni->verts[uni->num_verts].z = z + f_mul(r, s); uni->num_verts++; obj->num_verts++; } for (i = 0; i < det; i++) push_face(uni, obj, cap_bot_center, cap_bot_rim + i, cap_bot_rim + (i + 1) % det, wire); /* --- Fond haut --- */ cap_top_center = 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++; cap_top_rim = uni->num_verts; for (i = 0; i < det; i++) { th = (i * 360 / det) % 360; s = sintab[th]; cs = costab[th]; 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 + f_mul(r, cs); uni->verts[uni->num_verts].y = y + half_h; uni->verts[uni->num_verts].z = z + f_mul(r, s); uni->num_verts++; obj->num_verts++; } for (i = 0; i < det; i++) push_face(uni, obj, cap_top_center, cap_top_rim + (i + 1) % det, cap_top_rim + i, wire); return obj; } /* --- I/O sur Mesh dynamique (non utilisé dans le pipeline principal) --- */ void save_mesh(Mesh *m, const char *fn) { 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) { Mesh *m; FILE *f = fopen(fname, "rb"); if (!f) return NULL; m = (Mesh*)malloc(sizeof(Mesh)); if (!m) return NULL; fread(&m->num_verts, sizeof(int), 1, f); fread(&m->num_faces, sizeof(int), 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); if (!m->verts || !m->v_normals || !m->faces) { free(m->verts); free(m->v_normals); free(m->faces); free(m); fclose(f); return NULL; } 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; free(m->verts); free(m->v_normals); free(m->faces); free(m); }