174 lines
5.7 KiB
C
174 lines
5.7 KiB
C
#include "defines.h"
|
|
|
|
fixed sintab[360], costab[360];
|
|
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);
|
|
}
|
|
|
|
void init_engine_math(void) {
|
|
#ifndef MINIMAL_PLAYER
|
|
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);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void mat3_mul(Matrix3 *res, Matrix3 *a, Matrix3 *b) {
|
|
Matrix3 tmp;
|
|
int i, j;
|
|
for (i = 0; i < 3; i++)
|
|
for (j = 0; j < 3; j++)
|
|
tmp.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]);
|
|
*res = tmp;
|
|
}
|
|
|
|
void mat3_rotate_x(Matrix3 *m, int angle) {
|
|
int a = ((angle % 360) + 360) % 360;
|
|
fixed c = costab[a], s = sintab[a];
|
|
mat3_identity(m);
|
|
m->m[1][1] = c;
|
|
m->m[1][2] = -s;
|
|
m->m[2][1] = s;
|
|
m->m[2][2] = c;
|
|
}
|
|
|
|
void mat3_rotate_y(Matrix3 *m, int angle) {
|
|
int a = ((angle % 360) + 360) % 360;
|
|
fixed c = costab[a], s = sintab[a];
|
|
mat3_identity(m);
|
|
m->m[0][0] = c;
|
|
m->m[0][2] = s;
|
|
m->m[2][0] = -s;
|
|
m->m[2][2] = c;
|
|
}
|
|
|
|
void mat3_rotate_z(Matrix3 *m, int angle) {
|
|
int a = ((angle % 360) + 360) % 360;
|
|
fixed c = costab[a], s = sintab[a];
|
|
mat3_identity(m);
|
|
m->m[0][0] = c;
|
|
m->m[0][1] = s;
|
|
m->m[1][0] = -s;
|
|
m->m[1][1] = c;
|
|
}
|
|
|
|
/* 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) {
|
|
Matrix3 rx, ry, rz, tmp, rot;
|
|
Vector3 *v, *n;
|
|
|
|
int i, vi;
|
|
fixed vx, vy, vz;
|
|
|
|
if (!obj || !uni) return;
|
|
|
|
/* Composition de la matrice de rotation * /
|
|
mat3_rotate_x(&rx, ax);
|
|
mat3_rotate_y(&ry, ay);
|
|
mat3_rotate_z(&rz, az);
|
|
mat3_mul(&tmp, &rx, &ry);
|
|
mat3_mul(&rot, &tmp, &rz);
|
|
|
|
/* Application à tous les sommets et normales de l'objet * /
|
|
for (i = 0; i < obj->num_verts; i++) {
|
|
vi = obj->vert_start + i;
|
|
v = &uni->verts[vi];
|
|
n = &uni->v_normals[vi];
|
|
|
|
/* 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]);
|
|
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]);
|
|
v->x = vx;
|
|
v->y = vy;
|
|
v->z = vz;
|
|
|
|
/* 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]);
|
|
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]);
|
|
n->x = vx;
|
|
n->y = vy;
|
|
n->z = vz;
|
|
}
|
|
}
|
|
*/
|
|
void render_universe(Universe *uni, Camera *cam, int mode) {
|
|
int o, i, vi, front;
|
|
fixed rx, ry, rz, pz, nz;
|
|
uint8_t wire_col;
|
|
Vector3 *v, *n;
|
|
Object3D *obj;
|
|
Face *f;
|
|
Point2D *p1, *p2, *p3;
|
|
|
|
for (o = 0; o < uni->num_objects; o++) {
|
|
obj = &uni->objects[o];
|
|
|
|
/* Transformation + projection de tous les sommets de cet objet */
|
|
for (i = 0; i < obj->num_verts; i++) {
|
|
vi = obj->vert_start + i;
|
|
v = &uni->verts[vi];
|
|
n = &uni->v_normals[vi];
|
|
|
|
rx = f_mul(v->x, obj->rot.m[0][0]) + f_mul(v->y, obj->rot.m[1][0]) + f_mul(v->z, obj->rot.m[2][0]) + obj->pos.x - cam->pos.x;
|
|
ry = f_mul(v->x, obj->rot.m[0][1]) + f_mul(v->y, obj->rot.m[1][1]) + f_mul(v->z, obj->rot.m[2][1]) + obj->pos.y - cam->pos.y;
|
|
rz = f_mul(v->x, obj->rot.m[0][2]) + f_mul(v->y, obj->rot.m[1][2]) + f_mul(v->z, obj->rot.m[2][2]) + obj->pos.z - cam->pos.z;
|
|
|
|
pz = (rz < int_to_f(20)) ? int_to_f(20) : rz;
|
|
v_cache[vi].z = pz;
|
|
v_cache[vi].x = 160 + f_to_int(f_div(rx << 8, pz));
|
|
v_cache[vi].y = 100 - f_to_int(f_div(ry << 8, pz));
|
|
|
|
nz = f_mul(n->x, obj->rot.m[0][2]) + f_mul(n->y, obj->rot.m[1][2]) + f_mul(n->z, obj->rot.m[2][2]);
|
|
v_cache[vi].intensity = (nz >= 0) ? int_to_f(1) : f_mul(-nz, int_to_f(14)) + int_to_f(1);
|
|
}
|
|
|
|
wire_col = (uint8_t)((obj->color << 4) | 15);
|
|
|
|
/* Rendu des faces */
|
|
for (i = 0; i < obj->num_faces; i++) {
|
|
f = &uni->faces[obj->face_start + i];
|
|
p1 = &v_cache[f->a];
|
|
p2 = &v_cache[f->b];
|
|
p3 = &v_cache[f->c];
|
|
front = ((p2->x - p1->x) * (p3->y - p1->y) - (p2->y - p1->y) * (p3->x - p1->x)) > 0;
|
|
|
|
switch (mode) {
|
|
case MODE_WIRE:
|
|
draw_line_z(p1, p2, wire_col, 0);
|
|
draw_line_z(p2, p3, wire_col, 0);
|
|
draw_line_z(p3, p1, wire_col, 0);
|
|
break;
|
|
case MODE_HIDDEN:
|
|
if (front) {
|
|
draw_line_z(p1, p2, wire_col, 1);
|
|
draw_line_z(p2, p3, wire_col, 1);
|
|
draw_line_z(p3, p1, wire_col, 1);
|
|
}
|
|
break;
|
|
case MODE_SOLID:
|
|
default:
|
|
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_gouraud(p1, p2, p3, obj->color);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|