boarfds
This commit is contained in:
parent
80d8141b5a
commit
eae91de89d
8 changed files with 641 additions and 280 deletions
|
|
@ -1,49 +1,25 @@
|
|||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#define f_to_int(a) ((a) >> 16)
|
||||
#define int_to_f(a) ((a) << 16)
|
||||
// #define f_mul(a, b) ((fixed)(((int64_t)(a) * (b)) >> 16))
|
||||
inline fixed f_mul(fixed a, fixed b) { return (fixed)(((int64_t)a * b) >> 16); }
|
||||
inline fixed f_div(fixed a, fixed b) {
|
||||
if (b == 0) return 0; // Évite la division par zéro
|
||||
return (fixed)(((int64_t)a << 16) / b);
|
||||
}
|
||||
|
||||
// Matrice 3x3 pour la rotation des normales et des sommets
|
||||
typedef struct { fixed m[3][3]; } Matrix3;
|
||||
fixed sintab[360], costab[360], inv_table[321];
|
||||
Point2D v_cache[MAX_VERTEX];
|
||||
|
||||
void mat3_identity(Matrix3 *mat) {
|
||||
memset(mat, 0, sizeof(Matrix3));
|
||||
mat->m[0][0] = mat->m[1][1] = mat->m[2][2] = int_to_f(1);
|
||||
}
|
||||
|
||||
static fixed sintab[360], costab[360], inv_table[321];
|
||||
|
||||
void init_engine_math() {
|
||||
for (int i = 0; i < 360; i++) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 360; i++) {
|
||||
double r = (double)i * 3.14159265 / 180.0;
|
||||
sintab[i] = (fixed)(sin(r) * 65536.0);
|
||||
costab[i] = (fixed)(cos(r) * 65536.0);
|
||||
}
|
||||
inv_table[0] = 0;
|
||||
for (int i = 1; i <= 320; i++) inv_table[i] = (int_to_f(1) / i);
|
||||
for (i = 1; i <= 320; i++) inv_table[i] = (int_to_f(1) / i);
|
||||
}
|
||||
|
||||
typedef struct { fixed x, y, z; } Vector3;
|
||||
|
||||
typedef struct { int a, b, c; uint8_t color; uint8_t force_wire; } Face;
|
||||
typedef struct { int x, y; fixed z; int intensity; } Point2D;
|
||||
|
||||
typedef struct {
|
||||
Vector3 *verts;
|
||||
Vector3 *v_normals;
|
||||
Face *faces;
|
||||
int num_verts, num_faces;
|
||||
} Mesh;
|
||||
|
||||
// Normalisation pour le Gouraud (à la création uniquement)
|
||||
void normalize(Vector3 *v) {
|
||||
double dx = (double)v->x, dy = (double)v->y, dz = (double)v->z;
|
||||
|
|
@ -53,4 +29,92 @@ void normalize(Vector3 *v) {
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
// Génère une matrice de rotation sur l'axe X
|
||||
void mat3_rotate_x(Matrix3 *m, int angle) {
|
||||
fixed c = costab[angle % 360];
|
||||
fixed s = sintab[angle % 360];
|
||||
mat3_identity(m);
|
||||
m->m[1][1] = c; m->m[1][2] = -s;
|
||||
m->m[2][1] = s; m->m[2][2] = c;
|
||||
}
|
||||
|
||||
// Génère une matrice de rotation sur l'axe Y
|
||||
void mat3_rotate_y(Matrix3 *m, int angle) {
|
||||
fixed c = costab[angle % 360];
|
||||
fixed s = sintab[angle % 360];
|
||||
mat3_identity(m);
|
||||
m->m[0][0] = c; m->m[0][2] = s;
|
||||
m->m[2][0] = -s; m->m[2][2] = c;
|
||||
}
|
||||
|
||||
// Multiplie deux matrices 3x3 : res = a * b
|
||||
void mat3_mul(Matrix3 *res, Matrix3 *a, Matrix3 *b) {
|
||||
int i, j;
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
res->m[i][j] = f_mul(a->m[i][0], b->m[0][j]) +
|
||||
f_mul(a->m[i][1], b->m[1][j]) +
|
||||
f_mul(a->m[i][2], b->m[2][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_scene(Mesh *m, Matrix3 *rot, int global_mode) {
|
||||
int i;
|
||||
fixed pz, rx, ry, rz;
|
||||
Vector3 *v;
|
||||
Vector3 *n;
|
||||
fixed nz;
|
||||
int intensity;
|
||||
|
||||
|
||||
for (i = 0; i < m->num_verts; i++) {
|
||||
v = &m->verts[i];
|
||||
n = &m->v_normals[i];
|
||||
|
||||
// --- 1. Rotation de la normale (pour la lumière) ---
|
||||
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]);
|
||||
intensity = f_to_int(nz * 15);
|
||||
if (intensity < 0) intensity = 0;
|
||||
|
||||
// --- 2. Rotation du sommet (LA PIÈCE MANQUANTE) ---
|
||||
// On applique la multiplication Matrice * Vecteur
|
||||
rx = f_mul(v->x, rot->m[0][0]) + f_mul(v->y, rot->m[1][0]) + f_mul(v->z, rot->m[2][0]);
|
||||
ry = f_mul(v->x, rot->m[0][1]) + f_mul(v->y, rot->m[1][1]) + f_mul(v->z, rot->m[2][1]);
|
||||
rz = f_mul(v->x, rot->m[0][2]) + f_mul(v->y, rot->m[1][2]) + f_mul(v->z, rot->m[2][2]);
|
||||
|
||||
// --- 3. Projection avec les coordonnées tournées ---
|
||||
pz = rz; // On utilise le Z tourné
|
||||
if (pz < int_to_f(10)) pz = int_to_f(10);
|
||||
|
||||
v_cache[i].z = pz;
|
||||
v_cache[i].intensity = intensity;
|
||||
v_cache[i].x = 160 + f_to_int(f_div(rx << 8, pz)); // On utilise rx tourné
|
||||
v_cache[i].y = 100 - f_to_int(f_div(ry << 8, pz)); // On utilise ry tourné
|
||||
}
|
||||
|
||||
for (i = 0; i < m->num_faces; i++) {
|
||||
Face *f = &m->faces[i];
|
||||
Point2D *p1 = &v_cache[f->a];
|
||||
Point2D *p2 = &v_cache[f->b];
|
||||
Point2D *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);
|
||||
draw_line_z(p1, p2, f->color, 1);
|
||||
draw_line_z(p2, p3, f->color, 1);
|
||||
draw_line_z(p3, p1, f->color, 1); // Ajouté pour fermer le triangle
|
||||
} else {
|
||||
fill_triangle_gouraud(p1, p2, p3, f->color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue