trim spaces and use 4 space instead of 2

This commit is contained in:
Mylloon 2021-12-22 02:17:16 +01:00
parent db59cc2a85
commit 0b62517c35
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
6 changed files with 894 additions and 893 deletions

View file

@ -17,141 +17,141 @@
* quadrilatère "debout" et à la profondeur 0. Il fait la hauteur et * quadrilatère "debout" et à la profondeur 0. Il fait la hauteur et
* la largeur du cube unitaire (-1 à 1).*/ * la largeur du cube unitaire (-1 à 1).*/
surface_t * mk_quad(void) { surface_t * mk_quad(void) {
static const float static const float
data[] = { data[] = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f,
1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f
}; };
static const int order[] = { 0, 1, 2, 2, 1, 3 }; static const int order[] = { 0, 1, 2, 2, 1, 3 };
surface_t * s; surface_t * s;
/* on met du jaune partout */ /* on met du jaune partout */
const vec4 color0 = { 1.0f, 1.0f, 0.0f, 1.0f }; const vec4 color0 = { 1.0f, 1.0f, 0.0f, 1.0f };
triangle_t t[2]; triangle_t t[2];
int i, j, k, o; int i, j, k, o;
for(i = 0, o = 0; i < 2; ++i) for(i = 0, o = 0; i < 2; ++i)
for(j = 0; j < 3; ++j, ++o) { for(j = 0; j < 3; ++j, ++o) {
k = order[o] * 8; k = order[o] * 8;
t[i].v[j].position = *(vec4 *)&(data[k]); t[i].v[j].position = *(vec4 *)&(data[k]);
t[i].v[j].position.w = 1.0f; t[i].v[j].position.w = 1.0f;
t[i].v[j].normal = *(vec3 *)&(data[k + 3]); t[i].v[j].normal = *(vec3 *)&(data[k + 3]);
t[i].v[j].texCoord = *(vec2 *)&(data[k + 6]); t[i].v[j].texCoord = *(vec2 *)&(data[k + 6]);
t[i].v[j].color0 = color0; t[i].v[j].color0 = color0;
} }
s = new_surface(t, 2, 1, 1); s = new_surface(t, 2, 1, 1);
snormals(s); snormals(s);
return s; return s;
} }
/*!\brief fabrique et renvoie une surface représentant un /*!\brief fabrique et renvoie une surface représentant un
* cube unitaire (de -1 à 1).*/ * cube unitaire (de -1 à 1).*/
surface_t * mk_cube(void) { surface_t * mk_cube(void) {
const float const float
data[] = { data[] = {
/* front */ /* front */
-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
/* back */ /* back */
1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
/* right */ /* right */
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
/* left */ /* left */
-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
/* top */ /* top */
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
/* bottom */ /* bottom */
-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f
}; };
const int order[] = { 0, 1, 2, 2, 1, 3 }; const int order[] = { 0, 1, 2, 2, 1, 3 };
surface_t * s; surface_t * s;
/* on met du vert-clair partout */ /* on met du vert-clair partout */
const vec4 color0 = { 0.5f, 1.0f, 0.0f, 1.0f }; const vec4 color0 = { 0.5f, 1.0f, 0.0f, 1.0f };
triangle_t t[12]; triangle_t t[12];
int i, j, k, o; int i, j, k, o;
for(i = 0, o = 0; i < 12; ++i) for(i = 0, o = 0; i < 12; ++i)
for(j = 0; j < 3; ++j, ++o) { for(j = 0; j < 3; ++j, ++o) {
k = 8 * (order[o % 6] + 4 * (i / 2)); k = 8 * (order[o % 6] + 4 * (i / 2));
t[i].v[j].position = *(vec4 *)&(data[k]); t[i].v[j].position = *(vec4 *)&(data[k]);
t[i].v[j].position.w = 1.0f; t[i].v[j].position.w = 1.0f;
t[i].v[j].normal = *(vec3 *)&(data[k + 3]); t[i].v[j].normal = *(vec3 *)&(data[k + 3]);
t[i].v[j].texCoord = *(vec2 *)&(data[k + 6]); t[i].v[j].texCoord = *(vec2 *)&(data[k + 6]);
t[i].v[j].color0 = color0; t[i].v[j].color0 = color0;
} }
s = new_surface(t, 12, 1, 1); s = new_surface(t, 12, 1, 1);
snormals(s); snormals(s);
return s; return s;
} }
/*!\brief fabrique et renvoie une surface représentant une sphère /*!\brief fabrique et renvoie une surface représentant une sphère
* centrée en zéro et de rayon 1. Elle est découpée en \a longitudes * centrée en zéro et de rayon 1. Elle est découpée en \a longitudes
* longitudes et \a latitudes latitudes. */ * longitudes et \a latitudes latitudes. */
surface_t * mk_sphere(int longitudes, int latitudes) { surface_t * mk_sphere(int longitudes, int latitudes) {
triangle_t * t; triangle_t * t;
vertex_t * data; vertex_t * data;
double phi, theta, r, y; double phi, theta, r, y;
double c2MPI_Long = 2.0 * M_PI / longitudes; double c2MPI_Long = 2.0 * M_PI / longitudes;
double cMPI_Lat = M_PI / latitudes; double cMPI_Lat = M_PI / latitudes;
/* on met du vert-clair partout */ /* on met du vert-clair partout */
const vec4 color0 = { 0.5f, 1.0f, 0.0f, 1.0f }; const vec4 color0 = { 0.5f, 1.0f, 0.0f, 1.0f };
int z, nz, x, nx, zw, nzw, k, n = 2 * longitudes * latitudes; int z, nz, x, nx, zw, nzw, k, n = 2 * longitudes * latitudes;
assert(n); assert(n);
data = malloc((longitudes + 1) * (latitudes + 1) * sizeof *data); data = malloc((longitudes + 1) * (latitudes + 1) * sizeof *data);
assert(data); assert(data);
t = malloc(n * sizeof *t); t = malloc(n * sizeof *t);
assert(t); assert(t);
for(z = 0, k = 0; z <= latitudes; ++z) { for(z = 0, k = 0; z <= latitudes; ++z) {
theta = -M_PI_2 + z * cMPI_Lat; theta = -M_PI_2 + z * cMPI_Lat;
y = sin(theta); y = sin(theta);
r = cos(theta); r = cos(theta);
for(x = 0; x <= longitudes; ++x, ++k) { for(x = 0; x <= longitudes; ++x, ++k) {
phi = x * c2MPI_Long; phi = x * c2MPI_Long;
data[k].position.x = r * cos(phi); data[k].position.x = r * cos(phi);
data[k].position.y = y; data[k].position.y = y;
data[k].position.z = r * sin(phi); data[k].position.z = r * sin(phi);
data[k].position.w = 1.0f; data[k].position.w = 1.0f;
data[k].texCoord.x = phi / (2.0 * M_PI); data[k].texCoord.x = phi / (2.0 * M_PI);
data[k].texCoord.y = (theta + M_PI_2) / M_PI; data[k].texCoord.y = (theta + M_PI_2) / M_PI;
data[k].color0 = color0; data[k].color0 = color0;
/* gcc 7.5 et plus abusent : data[k].normal = *(vec3 *)&(data[k].position); */ /* gcc 7.5 et plus abusent : data[k].normal = *(vec3 *)&(data[k].position); */
data[k].normal.x = data[k].position.x; data[k].normal.x = data[k].position.x;
data[k].normal.y = data[k].position.y; data[k].normal.y = data[k].position.y;
data[k].normal.z = data[k].position.z; data[k].normal.z = data[k].position.z;
}
} }
} for(z = 0, k = 0; z < latitudes; ++z) {
for(z = 0, k = 0; z < latitudes; ++z) { nz = z + 1;
nz = z + 1; zw = z * (longitudes + 1);
zw = z * (longitudes + 1); nzw = nz * (longitudes + 1);
nzw = nz * (longitudes + 1); for(x = 0; x < longitudes; ++x) {
for(x = 0; x < longitudes; ++x) { nx = x + 1;
nx = x + 1; t[k].v[0] = data[zw + x];
t[k].v[0] = data[zw + x]; t[k].v[1] = data[nzw + x];
t[k].v[1] = data[nzw + x]; t[k].v[2] = data[zw + nx];
t[k].v[2] = data[zw + nx]; tnormal(&t[k]);++k;
tnormal(&t[k]);++k; t[k].v[0] = data[zw + nx];
t[k].v[0] = data[zw + nx]; t[k].v[1] = data[nzw + x];
t[k].v[1] = data[nzw + x]; t[k].v[2] = data[nzw + nx];
t[k].v[2] = data[nzw + nx]; tnormal(&t[k]);++k;
tnormal(&t[k]);++k; }
} }
} free(data);
free(data); return new_surface(t, n, 0, 1);
return new_surface(t, n, 0, 1);
} }

View file

@ -53,71 +53,72 @@ static int _perpective_correction = 0;
/*!\brief transforme et rastérise l'ensemble des triangles de la /*!\brief transforme et rastérise l'ensemble des triangles de la
* surface. */ * surface. */
void transform_n_rasterize(surface_t * s, float * model_view_matrix, float * projection_matrix) { void transform_n_rasterize(surface_t * s, float * model_view_matrix, float * projection_matrix) {
int i; int i;
/* la première fois allouer le depth buffer */ /* la première fois allouer le depth buffer */
if(_depth == NULL) { if(_depth == NULL) {
_depth = calloc(gl4dpGetWidth() * gl4dpGetHeight(), sizeof *_depth); _depth = calloc(gl4dpGetWidth() * gl4dpGetHeight(), sizeof *_depth);
assert(_depth); assert(_depth);
atexit(pquit); atexit(pquit);
} }
/* si projection_matrix[15] est à 1, c'est une projection orthogonale, pas /* si projection_matrix[15] est à 1, c'est une projection orthogonale, pas
* besoin de correction de perspective */ * besoin de correction de perspective */
_perpective_correction = projection_matrix[15] == 1.0f ? 0 : 1; _perpective_correction = projection_matrix[15] == 1.0f ? 0 : 1;
/* le viewport est fixe ; \todo peut devenir paramétrable ... */ /* le viewport est fixe ; \todo peut devenir paramétrable ... */
float viewport[] = { 0.0f, 0.0f, (float)gl4dpGetWidth(), (float)gl4dpGetHeight() }; float viewport[] = { 0.0f, 0.0f, (float)gl4dpGetWidth(), (float)gl4dpGetHeight() };
stransform(s, model_view_matrix, projection_matrix, viewport); stransform(s, model_view_matrix, projection_matrix, viewport);
/* mettre en place la texture qui sera utilisée pour mapper la surface */ /* mettre en place la texture qui sera utilisée pour mapper la surface */
if(s->options & SO_USE_TEXTURE) if(s->options & SO_USE_TEXTURE)
set_texture(s->tex_id); set_texture(s->tex_id);
for(i = 0; i < s->n; ++i) { for(i = 0; i < s->n; ++i) {
/* si le triangle est déclaré CULL (par exemple en backface), le rejeter */ /* si le triangle est déclaré CULL (par exemple en backface), le rejeter */
if(s->t[i].state & PS_CULL ) continue; if(s->t[i].state & PS_CULL ) continue;
/* on rejette aussi les triangles complètement out */ /* on rejette aussi les triangles complètement out */
if(s->t[i].state & PS_TOTALLY_OUT) continue; if(s->t[i].state & PS_TOTALLY_OUT) continue;
/* "hack" pas terrible permettant de rejeter les triangles /* "hack" pas terrible permettant de rejeter les triangles
* partiellement out dont au moins un sommet est TOO_FAR (trop * partiellement out dont au moins un sommet est TOO_FAR (trop
* éloigné). Voir le fichier transformations.c pour voir comment * éloigné). Voir le fichier transformations.c pour voir comment
* améliorer ce traitement. */ * améliorer ce traitement. */
if( s->t[i].state & PS_PARTIALLY_OUT && if( s->t[i].state & PS_PARTIALLY_OUT &&
( (s->t[i].v[0].state & PS_TOO_FAR) || ( (s->t[i].v[0].state & PS_TOO_FAR) ||
(s->t[i].v[1].state & PS_TOO_FAR) || (s->t[i].v[1].state & PS_TOO_FAR) ||
(s->t[i].v[2].state & PS_TOO_FAR) ) ) (s->t[i].v[2].state & PS_TOO_FAR) )
continue; )
fill_triangle(s, &(s->t[i])); continue;
} fill_triangle(s, &(s->t[i]));
}
} }
/*!\brief effacer le buffer de profondeur (à chaque frame) pour /*!\brief effacer le buffer de profondeur (à chaque frame) pour
* réaliser le z-test */ * réaliser le z-test */
void clear_depth_map(void) { void clear_depth_map(void) {
if(_depth) { if(_depth) {
memset(_depth, 0, gl4dpGetWidth() * gl4dpGetHeight() * sizeof *_depth); memset(_depth, 0, gl4dpGetWidth() * gl4dpGetHeight() * sizeof *_depth);
} }
} }
/*!\brief met en place une texture pour être mappée sur la surface en cours */ /*!\brief met en place une texture pour être mappée sur la surface en cours */
void set_texture(GLuint screen) { void set_texture(GLuint screen) {
GLuint old_id = gl4dpGetTextureId(); /* au cas où */ GLuint old_id = gl4dpGetTextureId(); /* au cas où */
gl4dpSetScreen(screen); gl4dpSetScreen(screen);
_tex = gl4dpGetPixels(); _tex = gl4dpGetPixels();
_texW = gl4dpGetWidth(); _texW = gl4dpGetWidth();
_texH = gl4dpGetHeight(); _texH = gl4dpGetHeight();
if(old_id) if(old_id)
gl4dpSetScreen(old_id); gl4dpSetScreen(old_id);
} }
/*!\brief met à jour la fonction d'interpolation et de coloriage /*!\brief met à jour la fonction d'interpolation et de coloriage
* (shadingfunc) de la surface en fonction de ses options */ * (shadingfunc) de la surface en fonction de ses options */
void updatesfuncs(surface_t * s) { void updatesfuncs(surface_t * s) {
int t; int t;
if(s->options & SO_USE_TEXTURE) { if(s->options & SO_USE_TEXTURE) {
s->interpolatefunc = (t = s->options & SO_COLOR_MATERIAL) ? metainterpolate_all : metainterpolate_only_tex; s->interpolatefunc = (t = s->options & SO_COLOR_MATERIAL) ? metainterpolate_all : metainterpolate_only_tex;
s->shadingfunc = (s->options & SO_USE_COLOR) ? (t ? shading_all_CM : shading_all) : shading_only_tex; s->shadingfunc = (s->options & SO_USE_COLOR) ? (t ? shading_all_CM : shading_all) : shading_only_tex;
} else { } else {
s->interpolatefunc = (t = s->options & SO_COLOR_MATERIAL) ? metainterpolate_only_color : metainterpolate_none; s->interpolatefunc = (t = s->options & SO_COLOR_MATERIAL) ? metainterpolate_only_color : metainterpolate_none;
s->shadingfunc = (s->options & SO_USE_COLOR) ? (t ? shading_only_color_CM : shading_only_color) : shading_none;; s->shadingfunc = (s->options & SO_USE_COLOR) ? (t ? shading_only_color_CM : shading_only_color) : shading_none;;
} }
} }
/*!\brief fonction principale de ce fichier, elle dessine un triangle /*!\brief fonction principale de ce fichier, elle dessine un triangle
@ -125,251 +126,251 @@ void updatesfuncs(surface_t * s) {
* (interpolations bilinaires des attributs du sommet). * (interpolations bilinaires des attributs du sommet).
*/ */
inline void fill_triangle(surface_t * s, triangle_t * t) { inline void fill_triangle(surface_t * s, triangle_t * t) {
vertex_t * aG = NULL, * aD = NULL; vertex_t * aG = NULL, * aD = NULL;
int bas, median, haut, n, signe, i, h = gl4dpGetHeight(); int bas, median, haut, n, signe, i, h = gl4dpGetHeight();
if(t->v[0].y < t->v[1].y) { if(t->v[0].y < t->v[1].y) {
if(t->v[0].y < t->v[2].y) { if(t->v[0].y < t->v[2].y) {
bas = 0; bas = 0;
if(t->v[1].y < t->v[2].y) { if(t->v[1].y < t->v[2].y) {
median = 1; median = 1;
haut = 2; haut = 2;
} else { } else {
median = 2; median = 2;
haut = 1; haut = 1;
} }
} else { } else {
bas = 2; bas = 2;
median = 0; median = 0;
haut = 1; haut = 1;
}
} else { /* p0 au dessus de p1 */
if(t->v[1].y < t->v[2].y) {
bas = 1;
if(t->v[0].y < t->v[2].y) {
median = 0;
haut = 2;
} else {
median = 2;
haut = 0;
}
} else {
bas = 2;
median = 1;
haut = 0;
}
} }
} else { /* p0 au dessus de p1 */ n = t->v[haut].y - t->v[bas].y + 1;
if(t->v[1].y < t->v[2].y) { aG = malloc(n * sizeof *aG);
bas = 1; assert(aG);
if(t->v[0].y < t->v[2].y) { aD = malloc(n * sizeof *aD);
median = 0; assert(aD);
haut = 2; /* est-ce que Pm est à gauche (+) ou à droite (-) de la droite (Pb->Ph) ? */
} else { /* idée TODO?, un produit vectoriel pourrait s'avérer mieux */
median = 2; if(t->v[haut].x == t->v[bas].x || t->v[haut].y == t->v[bas].y) {
haut = 0; /* eq de la droite x = t->v[haut].x; ou y = t->v[haut].y; */
} signe = (t->v[median].x > t->v[haut].x) ? -1 : 1;
} else { } else {
bas = 2; /* eq ax + y + c = 0 */
median = 1; float a, c, x;
haut = 0; a = (t->v[haut].y - t->v[bas].y) / (float)(t->v[bas].x - t->v[haut].x);
c = -a * t->v[haut].x - t->v[haut].y;
/* on trouve le x sur la droite au même y que le median et on compare */
x = -(c + t->v[median].y) / a;
signe = (t->v[median].x >= x) ? -1 : 1;
} }
} if(signe < 0) { /* aG reçoit Ph->Pb, et aD reçoit Ph->Pm puis Pm vers Pb */
n = t->v[haut].y - t->v[bas].y + 1; abscisses(s, &(t->v[haut]), &(t->v[bas]), aG, 1);
aG = malloc(n * sizeof *aG); abscisses(s, &(t->v[haut]), &(t->v[median]), aD, 1);
assert(aG); abscisses(s, &(t->v[median]), &(t->v[bas]), &aD[t->v[haut].y - t->v[median].y], 0);
aD = malloc(n * sizeof *aD); } else { /* aG reçoit Ph->Pm puis Pm vers Pb, et aD reçoit Ph->Pb */
assert(aD); abscisses(s, &(t->v[haut]), &(t->v[bas]), aD, 1);
/* est-ce que Pm est à gauche (+) ou à droite (-) de la droite (Pb->Ph) ? */ abscisses(s, &(t->v[haut]), &(t->v[median]), aG, 1);
/* idée TODO?, un produit vectoriel pourrait s'avérer mieux */ abscisses(s, &(t->v[median]), &(t->v[bas]), &aG[t->v[haut].y - t->v[median].y], 0);
if(t->v[haut].x == t->v[bas].x || t->v[haut].y == t->v[bas].y) { }
/* eq de la droite x = t->v[haut].x; ou y = t->v[haut].y; */ for(i = 0; i < n; ++i) {
signe = (t->v[median].x > t->v[haut].x) ? -1 : 1; if( aG[i].y >= 0 && aG[i].y < h &&
} else { ( (aG[i].z >= 0 && aG[i].z <= 1) || (aD[i].z >= 0 && aD[i].z <= 1) ) )
/* eq ax + y + c = 0 */ horizontal_line(s, &aG[i], &aD[i]);
float a, c, x; }
a = (t->v[haut].y - t->v[bas].y) / (float)(t->v[bas].x - t->v[haut].x); free(aG);
c = -a * t->v[haut].x - t->v[haut].y; free(aD);
/* on trouve le x sur la droite au même y que le median et on compare */
x = -(c + t->v[median].y) / a;
signe = (t->v[median].x >= x) ? -1 : 1;
}
if(signe < 0) { /* aG reçoit Ph->Pb, et aD reçoit Ph->Pm puis Pm vers Pb */
abscisses(s, &(t->v[haut]), &(t->v[bas]), aG, 1);
abscisses(s, &(t->v[haut]), &(t->v[median]), aD, 1);
abscisses(s, &(t->v[median]), &(t->v[bas]), &aD[t->v[haut].y - t->v[median].y], 0);
} else { /* aG reçoit Ph->Pm puis Pm vers Pb, et aD reçoit Ph->Pb */
abscisses(s, &(t->v[haut]), &(t->v[bas]), aD, 1);
abscisses(s, &(t->v[haut]), &(t->v[median]), aG, 1);
abscisses(s, &(t->v[median]), &(t->v[bas]), &aG[t->v[haut].y - t->v[median].y], 0);
}
for(i = 0; i < n; ++i) {
if( aG[i].y >= 0 && aG[i].y < h &&
( (aG[i].z >= 0 && aG[i].z <= 1) || (aD[i].z >= 0 && aD[i].z <= 1) ) )
horizontal_line(s, &aG[i], &aD[i]);
}
free(aG);
free(aD);
} }
/*!\brief utilise Br'65 pour determiner les abscisses des segments du /*!\brief utilise Br'65 pour determiner les abscisses des segments du
* triangle à remplir (par \a horizontal_line). * triangle à remplir (par \a horizontal_line).
*/ */
inline void abscisses(surface_t * s, vertex_t * p0, vertex_t * p1, vertex_t * absc, int replace) { inline void abscisses(surface_t * s, vertex_t * p0, vertex_t * p1, vertex_t * absc, int replace) {
int u = p1->x - p0->x, v = p1->y - p0->y, pasX = u < 0 ? -1 : 1, pasY = v < 0 ? -1 : 1; int u = p1->x - p0->x, v = p1->y - p0->y, pasX = u < 0 ? -1 : 1, pasY = v < 0 ? -1 : 1;
float dmax = sqrtf(u * u + v * v), p; float dmax = sqrtf(u * u + v * v), p;
u = abs(u); v = abs(v); u = abs(u); v = abs(v);
if(u > v) { // 1er octan if(u > v) { // 1er octan
if(replace) { if(replace) {
int objX = (u + 1) * pasX; int objX = (u + 1) * pasX;
int delta = u - 2 * v, incH = -2 * v, incO = 2 * u - 2 * v; int delta = u - 2 * v, incH = -2 * v, incO = 2 * u - 2 * v;
for (int x = 0, y = 0, k = 0; x != objX; x += pasX) { for (int x = 0, y = 0, k = 0; x != objX; x += pasX) {
absc[k].x = x + p0->x; absc[k].x = x + p0->x;
absc[k].y = y + p0->y; absc[k].y = y + p0->y;
p = sqrtf(x * x + y * y) / dmax; p = sqrtf(x * x + y * y) / dmax;
s->interpolatefunc(&absc[k], p0, p1, 1.0f - p, p); s->interpolatefunc(&absc[k], p0, p1, 1.0f - p, p);
if(delta < 0) { if(delta < 0) {
++k; ++k;
y += pasY; y += pasY;
delta += incO; delta += incO;
} else } else
delta += incH; delta += incH;
} }
} else { } else {
int objX = (u + 1) * pasX; int objX = (u + 1) * pasX;
int delta = u - 2 * v, incH = -2 * v, incO = 2 * u - 2 * v; int delta = u - 2 * v, incH = -2 * v, incO = 2 * u - 2 * v;
for (int x = 0, y = 0, k = 0, done = 0; x != objX; x += pasX) { for (int x = 0, y = 0, k = 0, done = 0; x != objX; x += pasX) {
if(!done) { if(!done) {
absc[k].x = x + p0->x; absc[k].x = x + p0->x;
absc[k].y = y + p0->y; absc[k].y = y + p0->y;
p = sqrtf(x * x + y * y) / dmax; p = sqrtf(x * x + y * y) / dmax;
s->interpolatefunc(&absc[k], p0, p1, 1.0f - p, p); s->interpolatefunc(&absc[k], p0, p1, 1.0f - p, p);
done = 1; done = 1;
} }
if(delta < 0) { if(delta < 0) {
++k; ++k;
done = 0; done = 0;
y += pasY; y += pasY;
delta += incO; delta += incO;
} else } else
delta += incH; delta += incH;
} }
}
} else { // 2eme octan
int objY = (v + 1) * pasY;
int delta = v - 2 * u, incH = -2 * u, incO = 2 * v - 2 * u;
for (int x = 0, y = 0, k = 0; y != objY; y += pasY) {
absc[k].x = x + p0->x;
absc[k].y = y + p0->y;
p = sqrtf(x * x + y * y) / dmax;
s->interpolatefunc(&absc[k], p0, p1, 1.0f - p, p);
++k;
if(delta < 0) {
x += pasX;
delta += incO;
} else
delta += incH;
}
} }
} else { // 2eme octan
int objY = (v + 1) * pasY;
int delta = v - 2 * u, incH = -2 * u, incO = 2 * v - 2 * u;
for (int x = 0, y = 0, k = 0; y != objY; y += pasY) {
absc[k].x = x + p0->x;
absc[k].y = y + p0->y;
p = sqrtf(x * x + y * y) / dmax;
s->interpolatefunc(&absc[k], p0, p1, 1.0f - p, p);
++k;
if(delta < 0) {
x += pasX;
delta += incO;
} else
delta += incH;
}
}
} }
/*!\brief remplissage par droite horizontale entre deux abscisses */ /*!\brief remplissage par droite horizontale entre deux abscisses */
inline void horizontal_line(surface_t * s, vertex_t * vG, vertex_t * vD) { inline void horizontal_line(surface_t * s, vertex_t * vG, vertex_t * vD) {
int w = gl4dpGetWidth(), x, yw = vG->y * w; int w = gl4dpGetWidth(), x, yw = vG->y * w;
GLuint * image = gl4dpGetPixels(); GLuint * image = gl4dpGetPixels();
float dmax = vD->x - vG->x, p, deltap; float dmax = vD->x - vG->x, p, deltap;
vertex_t v; vertex_t v;
/* il reste d'autres optims possibles */ /* il reste d'autres optims possibles */
for(x = vG->x, p = 0.0f, deltap = 1.0f / dmax; x <= vD->x; ++x, p += deltap) for(x = vG->x, p = 0.0f, deltap = 1.0f / dmax; x <= vD->x; ++x, p += deltap)
if(x >= 0 && x < w) { if(x >= 0 && x < w) {
s->interpolatefunc(&v, vG, vD, 1.0f - p, p); s->interpolatefunc(&v, vG, vD, 1.0f - p, p);
if(v.z < 0 || v.z > 1 || v.z < _depth[yw + x]) { continue; } if(v.z < 0 || v.z > 1 || v.z < _depth[yw + x]) { continue; }
s->shadingfunc(s, &image[yw + x], &v); s->shadingfunc(s, &image[yw + x], &v);
_depth[yw + x] = v.z; _depth[yw + x] = v.z;
} }
} }
/*!\brief aucune couleur n'est inscrite */ /*!\brief aucune couleur n'est inscrite */
inline void shading_none(surface_t * s, GLuint * pcolor, vertex_t * v) { inline void shading_none(surface_t * s, GLuint * pcolor, vertex_t * v) {
//vide pour l'instant, à prévoir le z-buffer //vide pour l'instant, à prévoir le z-buffer
} }
/*!\brief la couleur du pixel est tirée uniquement de la texture */ /*!\brief la couleur du pixel est tirée uniquement de la texture */
inline void shading_only_tex(surface_t * s, GLuint * pcolor, vertex_t * v) { inline void shading_only_tex(surface_t * s, GLuint * pcolor, vertex_t * v) {
int xt, yt, ct; int xt, yt, ct;
GLubyte r, g, b, a; GLubyte r, g, b, a;
xt = (int)(v->texCoord.x * (_texW - EPSILON)); xt = (int)(v->texCoord.x * (_texW - EPSILON));
if(xt < 0) { if(xt < 0) {
xt = xt % (-_texW); xt = xt % (-_texW);
while(xt < 0) xt += _texW; while(xt < 0) xt += _texW;
} else } else
xt = xt % _texW; xt = xt % _texW;
yt = (int)(v->texCoord.y * (_texH - EPSILON)); yt = (int)(v->texCoord.y * (_texH - EPSILON));
if(yt < 0) { if(yt < 0) {
yt = yt % (-_texH); yt = yt % (-_texH);
while(yt < 0) yt += _texH; while(yt < 0) yt += _texH;
} else } else
yt = yt % _texH; yt = yt % _texH;
ct = yt * _texW + xt; ct = yt * _texW + xt;
*pcolor = _tex[yt * _texW + xt]; *pcolor = _tex[yt * _texW + xt];
r = (GLubyte)( red(_tex[ct]) * v->li); r = (GLubyte)( red(_tex[ct]) * v->li);
g = (GLubyte)(green(_tex[ct]) * v->li); g = (GLubyte)(green(_tex[ct]) * v->li);
b = (GLubyte)( blue(_tex[ct]) * v->li); b = (GLubyte)( blue(_tex[ct]) * v->li);
a = (GLubyte) alpha(_tex[ct]); a = (GLubyte) alpha(_tex[ct]);
*pcolor = rgba(r, g, b, a); *pcolor = rgba(r, g, b, a);
} }
/*!\brief la couleur du pixel est tirée de la couleur interpolée */ /*!\brief la couleur du pixel est tirée de la couleur interpolée */
inline void shading_only_color_CM(surface_t * s, GLuint * pcolor, vertex_t * v) { inline void shading_only_color_CM(surface_t * s, GLuint * pcolor, vertex_t * v) {
GLubyte r, g, b, a; GLubyte r, g, b, a;
r = (GLubyte)(v->li * v->icolor.x * (255 + EPSILON)); r = (GLubyte)(v->li * v->icolor.x * (255 + EPSILON));
g = (GLubyte)(v->li * v->icolor.y * (255 + EPSILON)); g = (GLubyte)(v->li * v->icolor.y * (255 + EPSILON));
b = (GLubyte)(v->li * v->icolor.z * (255 + EPSILON)); b = (GLubyte)(v->li * v->icolor.z * (255 + EPSILON));
a = (GLubyte)(v->icolor.w * (255 + EPSILON)); a = (GLubyte)(v->icolor.w * (255 + EPSILON));
*pcolor = rgba(r, g, b, a); *pcolor = rgba(r, g, b, a);
} }
/*!\brief la couleur du pixel est tirée de la couleur diffuse de la /*!\brief la couleur du pixel est tirée de la couleur diffuse de la
* surface */ * surface */
inline void shading_only_color(surface_t * s, GLuint * pcolor, vertex_t * v) { inline void shading_only_color(surface_t * s, GLuint * pcolor, vertex_t * v) {
GLubyte r, g, b, a; GLubyte r, g, b, a;
r = (GLubyte)(v->li * s->dcolor.x * (255 + EPSILON)); r = (GLubyte)(v->li * s->dcolor.x * (255 + EPSILON));
g = (GLubyte)(v->li * s->dcolor.y * (255 + EPSILON)); g = (GLubyte)(v->li * s->dcolor.y * (255 + EPSILON));
b = (GLubyte)(v->li * s->dcolor.z * (255 + EPSILON)); b = (GLubyte)(v->li * s->dcolor.z * (255 + EPSILON));
a = (GLubyte)(s->dcolor.w * (255 + EPSILON)); a = (GLubyte)(s->dcolor.w * (255 + EPSILON));
*pcolor = rgba(r, g, b, a); *pcolor = rgba(r, g, b, a);
} }
/*!\brief la couleur du pixel est le produit de la couleur interpolée /*!\brief la couleur du pixel est le produit de la couleur interpolée
* et de la texture */ * et de la texture */
inline void shading_all_CM(surface_t * s, GLuint * pcolor, vertex_t * v) { inline void shading_all_CM(surface_t * s, GLuint * pcolor, vertex_t * v) {
GLubyte r, g, b, a; GLubyte r, g, b, a;
int xt, yt, ct; int xt, yt, ct;
xt = (int)(v->texCoord.x * (_texW - EPSILON)); xt = (int)(v->texCoord.x * (_texW - EPSILON));
if(xt < 0) { if(xt < 0) {
xt = xt % (-_texW); xt = xt % (-_texW);
while(xt < 0) xt += _texW; while(xt < 0) xt += _texW;
} else } else
xt = xt % _texW; xt = xt % _texW;
yt = (int)(v->texCoord.y * (_texH - EPSILON)); yt = (int)(v->texCoord.y * (_texH - EPSILON));
if(yt < 0) { if(yt < 0) {
yt = yt % (-_texH); yt = yt % (-_texH);
while(yt < 0) yt += _texH; while(yt < 0) yt += _texH;
} else } else
yt = yt % _texH; yt = yt % _texH;
ct = yt * _texW + xt; ct = yt * _texW + xt;
r = (GLubyte)(( red(_tex[ct]) + EPSILON) * v->li * v->icolor.x); r = (GLubyte)(( red(_tex[ct]) + EPSILON) * v->li * v->icolor.x);
g = (GLubyte)((green(_tex[ct]) + EPSILON) * v->li * v->icolor.y); g = (GLubyte)((green(_tex[ct]) + EPSILON) * v->li * v->icolor.y);
b = (GLubyte)(( blue(_tex[ct]) + EPSILON) * v->li * v->icolor.z); b = (GLubyte)(( blue(_tex[ct]) + EPSILON) * v->li * v->icolor.z);
a = (GLubyte)((alpha(_tex[ct]) + EPSILON) * v->icolor.w); a = (GLubyte)((alpha(_tex[ct]) + EPSILON) * v->icolor.w);
*pcolor = rgba(r, g, b, a); *pcolor = rgba(r, g, b, a);
} }
/*!\brief la couleur du pixel est le produit de la couleur diffuse /*!\brief la couleur du pixel est le produit de la couleur diffuse
* de la surface et de la texture */ * de la surface et de la texture */
inline void shading_all(surface_t * s, GLuint * pcolor, vertex_t * v) { inline void shading_all(surface_t * s, GLuint * pcolor, vertex_t * v) {
GLubyte r, g, b, a; GLubyte r, g, b, a;
int xt, yt, ct; int xt, yt, ct;
xt = (int)(v->texCoord.x * (_texW - EPSILON)); xt = (int)(v->texCoord.x * (_texW - EPSILON));
if(xt < 0) { if(xt < 0) {
xt = xt % (-_texW); xt = xt % (-_texW);
while(xt < 0) xt += _texW; while(xt < 0) xt += _texW;
} else } else
xt = xt % _texW; xt = xt % _texW;
yt = (int)(v->texCoord.y * (_texH - EPSILON)); yt = (int)(v->texCoord.y * (_texH - EPSILON));
if(yt < 0) { if(yt < 0) {
yt = yt % (-_texH); yt = yt % (-_texH);
while(yt < 0) yt += _texH; while(yt < 0) yt += _texH;
} else } else
yt = yt % _texH; yt = yt % _texH;
ct = yt * _texW + xt; ct = yt * _texW + xt;
r = (GLubyte)(( red(_tex[ct]) + EPSILON) * v->li * s->dcolor.x); r = (GLubyte)(( red(_tex[ct]) + EPSILON) * v->li * s->dcolor.x);
g = (GLubyte)((green(_tex[ct]) + EPSILON) * v->li * s->dcolor.y); g = (GLubyte)((green(_tex[ct]) + EPSILON) * v->li * s->dcolor.y);
b = (GLubyte)(( blue(_tex[ct]) + EPSILON) * v->li * s->dcolor.z); b = (GLubyte)(( blue(_tex[ct]) + EPSILON) * v->li * s->dcolor.z);
a = (GLubyte)((alpha(_tex[ct]) + EPSILON) * s->dcolor.w); a = (GLubyte)((alpha(_tex[ct]) + EPSILON) * s->dcolor.w);
*pcolor = rgba(r, g, b, a); *pcolor = rgba(r, g, b, a);
} }
/*!\brief interpolation de plusieurs floattants (entre \a s et \a e) /*!\brief interpolation de plusieurs floattants (entre \a s et \a e)
@ -378,78 +379,78 @@ inline void shading_all(surface_t * s, GLuint * pcolor, vertex_t * v) {
* \todo un pointeur de fonction pour éviter un test s'il faut * \todo un pointeur de fonction pour éviter un test s'il faut
* un _perpective_correction != 0 ??? */ * un _perpective_correction != 0 ??? */
inline void interpolate(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb, int s, int e) { inline void interpolate(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb, int s, int e) {
int i; int i;
float * pr = (float *)&(r->texCoord); float * pr = (float *)&(r->texCoord);
float * pa = (float *)&(a->texCoord); float * pa = (float *)&(a->texCoord);
float * pb = (float *)&(b->texCoord); float * pb = (float *)&(b->texCoord);
/* Correction de l'interpolation par rapport à la perspective, le z /* Correction de l'interpolation par rapport à la perspective, le z
* joue un rôle dans les distances, il est nécessaire de le * joue un rôle dans les distances, il est nécessaire de le
* réintégrer en modifiant les facteurs de proportion. * réintégrer en modifiant les facteurs de proportion.
* lien utile : https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/perspective-correct-interpolation-vertex-attributes * lien utile : https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/perspective-correct-interpolation-vertex-attributes
*/ */
if(_perpective_correction) { if(_perpective_correction) {
float z = 1.0f / (fa / a->zmod + fb / b->zmod); float z = 1.0f / (fa / a->zmod + fb / b->zmod);
if(e == 8) { /* attention il faut que cet indice colle avec la position de la proriété z à partir de l'adresse texCoord */ if(e == 8) { /* attention il faut que cet indice colle avec la position de la proriété z à partir de l'adresse texCoord */
pr[e] = fa * pa[e] + fb * pb[e]; pr[e] = fa * pa[e] + fb * pb[e];
e = 7; e = 7;
}
fa = z * fa / a->zmod; fb = z * fb / b->zmod;
} }
fa = z * fa / a->zmod; fb = z * fb / b->zmod; for(i = s; i <= e; ++i)
} pr[i] = fa * pa[i] + fb * pb[i];
for(i = s; i <= e; ++i)
pr[i] = fa * pa[i] + fb * pb[i];
} }
/*!\brief meta-fonction pour appeler \a interpolate, demande /*!\brief meta-fonction pour appeler \a interpolate, demande
* uniquement l'interpolation des z */ * uniquement l'interpolation des z */
inline void metainterpolate_none(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb) { inline void metainterpolate_none(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb) {
interpolate(r, a, b, fa, fb, 6, 8); interpolate(r, a, b, fa, fb, 6, 8);
} }
/*!\brief meta-fonction pour appeler \a interpolate, demande /*!\brief meta-fonction pour appeler \a interpolate, demande
* uniquement l'interpolation des coord. de texture et les z */ * uniquement l'interpolation des coord. de texture et les z */
inline void metainterpolate_only_tex(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb) { inline void metainterpolate_only_tex(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb) {
interpolate(r, a, b, fa, fb, 0, 1); interpolate(r, a, b, fa, fb, 0, 1);
interpolate(r, a, b, fa, fb, 6, 8); interpolate(r, a, b, fa, fb, 6, 8);
} }
/*!\brief meta-fonction pour appeler \a interpolate, demande /*!\brief meta-fonction pour appeler \a interpolate, demande
* uniquement l'interpolation des couleurs et les z */ * uniquement l'interpolation des couleurs et les z */
inline void metainterpolate_only_color(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb) { inline void metainterpolate_only_color(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb) {
interpolate(r, a, b, fa, fb, 2, 8); interpolate(r, a, b, fa, fb, 2, 8);
} }
/*!\brief meta-fonction pour appeler \a interpolate, demande /*!\brief meta-fonction pour appeler \a interpolate, demande
* l'interpolation de l'ensemble des attributs */ * l'interpolation de l'ensemble des attributs */
inline void metainterpolate_all(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb) { inline void metainterpolate_all(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb) {
interpolate(r, a, b, fa, fb, 0, 8); interpolate(r, a, b, fa, fb, 0, 8);
} }
GLuint rgba(GLubyte r, GLubyte g, GLubyte b, GLubyte a) { GLuint rgba(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
return RGBA(r, g, b, a); return RGBA(r, g, b, a);
} }
GLubyte red(GLuint c) { GLubyte red(GLuint c) {
return RED(c); return RED(c);
} }
GLubyte green(GLuint c) { GLubyte green(GLuint c) {
return GREEN(c); return GREEN(c);
} }
GLubyte blue(GLuint c) { GLubyte blue(GLuint c) {
return BLUE(c); return BLUE(c);
} }
GLubyte alpha(GLuint c) { GLubyte alpha(GLuint c) {
return ALPHA(c); return ALPHA(c);
} }
/*!\brief au moment de quitter le programme désallouer la mémoire /*!\brief au moment de quitter le programme désallouer la mémoire
* utilisée pour _depth */ * utilisée pour _depth */
void pquit(void) { void pquit(void) {
if(_depth) { if(_depth) {
free(_depth); free(_depth);
_depth = NULL; _depth = NULL;
} }
} }

View file

@ -20,71 +20,71 @@
extern "C" { extern "C" {
# endif # endif
typedef enum pstate_t pstate_t; typedef enum pstate_t pstate_t;
typedef enum soptions_t soptions_t; typedef enum soptions_t soptions_t;
typedef struct vec4 vec4; typedef struct vec4 vec4;
typedef struct vec3 vec3; typedef struct vec3 vec3;
typedef struct vec2 vec2; typedef struct vec2 vec2;
typedef struct vertex_t vertex_t; typedef struct vertex_t vertex_t;
typedef struct triangle_t triangle_t; typedef struct triangle_t triangle_t;
typedef struct surface_t surface_t; typedef struct surface_t surface_t;
/*!\brief états pour les sommets ou les triangles */ /*!\brief états pour les sommets ou les triangles */
enum pstate_t { enum pstate_t {
PS_NONE = 0, PS_NONE = 0,
PS_TOTALLY_OUT = 1, PS_TOTALLY_OUT = 1,
PS_PARTIALLY_OUT = 2, PS_PARTIALLY_OUT = 2,
PS_CULL = 4, /* si en BACKFACE et que PS_CULL = 4, /* si en BACKFACE et que
SO_CULL_BACKFACES est actif */ SO_CULL_BACKFACES est actif */
PS_TOO_FAR = 8, PS_TOO_FAR = 8,
PS_OUT_LEFT = 16, PS_OUT_LEFT = 16,
PS_OUT_RIGHT = 32, PS_OUT_RIGHT = 32,
PS_OUT_BOTTOM = 64, PS_OUT_BOTTOM = 64,
PS_OUT_TOP = 128, PS_OUT_TOP = 128,
PS_OUT_NEAR = 256, PS_OUT_NEAR = 256,
PS_OUT_FAR = 512 PS_OUT_FAR = 512
}; };
/*!\brief options pour les surfaces */ /*!\brief options pour les surfaces */
enum soptions_t { enum soptions_t {
SO_NONE = 0, /* la surface n'a pas de rendu SO_NONE = 0, /* la surface n'a pas de rendu
"couleur" */ "couleur" */
SO_USE_TEXTURE = 1, /* utiliser la texture pour SO_USE_TEXTURE = 1, /* utiliser la texture pour
colorer (multiplication si colorer (multiplication si
SO_USE_COLOR est actif) */ SO_USE_COLOR est actif) */
SO_USE_COLOR = 2, /* utiliser la couleur de la SO_USE_COLOR = 2, /* utiliser la couleur de la
surface ou des sommets pour surface ou des sommets pour
colorer (multiplication si colorer (multiplication si
SO_USE_TEXTURE est actif) */ SO_USE_TEXTURE est actif) */
SO_COLOR_MATERIAL = 4, /* utiliser la couleur aux SO_COLOR_MATERIAL = 4, /* utiliser la couleur aux
sommets si actif sommets si actif
(nécessite aussi (nécessite aussi
l'activation de l'activation de
SO_USE_COLOR) */ SO_USE_COLOR) */
SO_CULL_BACKFACES = 8, /* active le fait de cacher SO_CULL_BACKFACES = 8, /* active le fait de cacher
les faces arrières */ les faces arrières */
SO_USE_LIGHTING = 16, /* active le calcul d'ombre SO_USE_LIGHTING = 16, /* active le calcul d'ombre
propre (Gouraud sur propre (Gouraud sur
diffus) */ diffus) */
SO_DEFAULT = SO_CULL_BACKFACES | SO_USE_COLOR /* comportement SO_DEFAULT = SO_CULL_BACKFACES | SO_USE_COLOR /* comportement
par par
défaut */ défaut */
}; };
struct vec4 { struct vec4 {
float x /* r */, y/* g */, z /* b */, w /* a */; float x /* r */, y/* g */, z /* b */, w /* a */;
}; };
struct vec2 { struct vec2 {
float x /* s */, y /* t */; float x /* s */, y /* t */;
}; };
struct vec3 { struct vec3 {
float x /* r */, y/* g */, z/* b */; float x /* r */, y/* g */, z/* b */;
}; };
/*!\brief le sommet et l'ensemble de ses attributs */ /*!\brief le sommet et l'ensemble de ses attributs */
struct vertex_t { struct vertex_t {
vec4 position; vec4 position;
vec4 color0; vec4 color0;
/* début des données à partir desquelles on peut interpoler en masse */ /* début des données à partir desquelles on peut interpoler en masse */
@ -92,68 +92,68 @@ extern "C" {
vec4 icolor; /* couleur à interpoler */ vec4 icolor; /* couleur à interpoler */
float li; /* intensité de lumière (lambertien) */ float li; /* intensité de lumière (lambertien) */
float zmod; /* z après modelview, sert à corriger float zmod; /* z après modelview, sert à corriger
l'interpolation par rapport à une projection en l'interpolation par rapport à une projection en
perspective */ perspective */
float z; /* ce z représente la depth */ float z; /* ce z représente la depth */
/* fin des données à partir desquelles on peut interpoler */ /* fin des données à partir desquelles on peut interpoler */
vec3 normal; /* interpolez les normales si vous implémentez Phong */ vec3 normal; /* interpolez les normales si vous implémentez Phong */
int x, y; int x, y;
enum pstate_t state; enum pstate_t state;
}; };
/*!\brief le triangle */ /*!\brief le triangle */
struct triangle_t { struct triangle_t {
vertex_t v[3]; vertex_t v[3];
vec3 normal; vec3 normal;
enum pstate_t state; enum pstate_t state;
}; };
/*!\brief la surface englobe plusieurs triangles et des options /*!\brief la surface englobe plusieurs triangles et des options
* telles que le type de rendu, la couleur diffuse ou la texture. * telles que le type de rendu, la couleur diffuse ou la texture.
*/ */
struct surface_t { struct surface_t {
int n; int n;
triangle_t * t; triangle_t * t;
GLuint tex_id; GLuint tex_id;
vec4 dcolor; /* couleur diffuse, ajoutez une couleur ambiante et vec4 dcolor; /* couleur diffuse, ajoutez une couleur ambiante et
spéculaire si vous souhaitez compléter le spéculaire si vous souhaitez compléter le
modèle */ modèle */
soptions_t options; /* paramétrage du rendu de la surface */ soptions_t options; /* paramétrage du rendu de la surface */
void (*interpolatefunc)(vertex_t *, vertex_t *, vertex_t *, float, float); void (*interpolatefunc)(vertex_t *, vertex_t *, vertex_t *, float, float);
void (*shadingfunc)(surface_t *, GLuint *, vertex_t *); void (*shadingfunc)(surface_t *, GLuint *, vertex_t *);
}; };
/* dans rasterize.c */ /* dans rasterize.c */
extern void transform_n_rasterize(surface_t * s, float * model_view_matrix, float * projection_matrix); extern void transform_n_rasterize(surface_t * s, float * model_view_matrix, float * projection_matrix);
extern void clear_depth_map(void); extern void clear_depth_map(void);
extern void set_texture(GLuint screen); extern void set_texture(GLuint screen);
extern void updatesfuncs(surface_t * s); extern void updatesfuncs(surface_t * s);
/* dans vtranform.c */ /* dans vtranform.c */
extern vertex_t vtransform(surface_t * s, vertex_t v, float * model_view_matrix, float * ti_model_view_matrix, float * projection_matrix, float * viewport); extern vertex_t vtransform(surface_t * s, vertex_t v, float * model_view_matrix, float * ti_model_view_matrix, float * projection_matrix, float * viewport);
extern void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport); extern void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport);
extern void mult_matrix(float * res, float * m); extern void mult_matrix(float * res, float * m);
extern void translate(float * m, float tx, float ty, float tz); extern void translate(float * m, float tx, float ty, float tz);
extern void rotate(float * m, float angle, float x, float y, float z); extern void rotate(float * m, float angle, float x, float y, float z);
extern void scale(float * m, float sx, float sy, float sz); extern void scale(float * m, float sx, float sy, float sz);
extern void lookAt(float * m, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ); extern void lookAt(float * m, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
/* dans surface.c */ /* dans surface.c */
extern void tnormal(triangle_t * t); extern void tnormal(triangle_t * t);
extern void snormals(surface_t * s); extern void snormals(surface_t * s);
extern void tnormals2vertices(surface_t * s); extern void tnormals2vertices(surface_t * s);
extern void set_texture_id(surface_t * s, GLuint tex_id); extern void set_texture_id(surface_t * s, GLuint tex_id);
extern void set_diffuse_color(surface_t * s, vec4 dcolor); extern void set_diffuse_color(surface_t * s, vec4 dcolor);
extern void enable_surface_option(surface_t * s, soptions_t option); extern void enable_surface_option(surface_t * s, soptions_t option);
extern void disable_surface_option(surface_t * s, soptions_t option); extern void disable_surface_option(surface_t * s, soptions_t option);
extern surface_t * new_surface(triangle_t * t, int n, int duplicateTriangles, int hasNormals); extern surface_t * new_surface(triangle_t * t, int n, int duplicateTriangles, int hasNormals);
extern void free_surface(surface_t * s); extern void free_surface(surface_t * s);
extern GLuint get_texture_from_BMP(const char * filename); extern GLuint get_texture_from_BMP(const char * filename);
/* dans geometry.c */ /* dans geometry.c */
extern surface_t * mk_quad(void); extern surface_t * mk_quad(void);
extern surface_t * mk_cube(void); extern surface_t * mk_cube(void);
extern surface_t * mk_sphere(int longitudes, int latitudes); extern surface_t * mk_sphere(int longitudes, int latitudes);
# ifdef __cplusplus # ifdef __cplusplus
} }
# endif # endif

122
surface.c
View file

@ -13,14 +13,14 @@
/*!\brief calcule le vecteur normal à un triangle */ /*!\brief calcule le vecteur normal à un triangle */
void tnormal(triangle_t * t) { void tnormal(triangle_t * t) {
vec3 u = { vec3 u = {
t->v[1].position.x - t->v[0].position.x, t->v[1].position.x - t->v[0].position.x,
t->v[1].position.y - t->v[0].position.y, t->v[1].position.y - t->v[0].position.y,
t->v[1].position.z - t->v[0].position.z t->v[1].position.z - t->v[0].position.z
}; };
vec3 v = { vec3 v = {
t->v[2].position.x - t->v[0].position.x, t->v[2].position.x - t->v[0].position.x,
t->v[2].position.y - t->v[0].position.y, t->v[2].position.y - t->v[0].position.y,
t->v[2].position.z - t->v[0].position.z t->v[2].position.z - t->v[0].position.z
}; };
MVEC3CROSS((float *)&(t->normal), (float *)&u, (float *)&v); MVEC3CROSS((float *)&(t->normal), (float *)&u, (float *)&v);
MVEC3NORMALIZE((float *)&(t->normal)); MVEC3NORMALIZE((float *)&(t->normal));
@ -28,40 +28,40 @@ void tnormal(triangle_t * t) {
/*!\brief calcule les vecteurs normaux aux triangles de la surface */ /*!\brief calcule les vecteurs normaux aux triangles de la surface */
void snormals(surface_t * s) { void snormals(surface_t * s) {
int i; int i;
for(i = 0; i < s->n; ++i) for(i = 0; i < s->n; ++i)
tnormal(&(s->t[i])); tnormal(&(s->t[i]));
} }
/*!\brief affecte les normales aux triangles de la surface à ses vertices */ /*!\brief affecte les normales aux triangles de la surface à ses vertices */
void tnormals2vertices(surface_t * s) { void tnormals2vertices(surface_t * s) {
int i; int i;
for(i = 0; i < s->n; ++i) for(i = 0; i < s->n; ++i)
s->t[i].v[0].normal = s->t[i].v[1].normal = s->t[i].v[2].normal = s->t[i].normal; s->t[i].v[0].normal = s->t[i].v[1].normal = s->t[i].v[2].normal = s->t[i].normal;
} }
/*!\brief affecte l'identifiant de texture de la surface */ /*!\brief affecte l'identifiant de texture de la surface */
void set_texture_id(surface_t * s, GLuint tex_id) { void set_texture_id(surface_t * s, GLuint tex_id) {
s->tex_id = tex_id; s->tex_id = tex_id;
} }
/*!\brief affecte la couleur diffuse de la surface */ /*!\brief affecte la couleur diffuse de la surface */
void set_diffuse_color(surface_t * s, vec4 dcolor) { void set_diffuse_color(surface_t * s, vec4 dcolor) {
s->dcolor = dcolor; s->dcolor = dcolor;
} }
/*!\brief active une option de la surface */ /*!\brief active une option de la surface */
void enable_surface_option(surface_t * s, soptions_t option) { void enable_surface_option(surface_t * s, soptions_t option) {
if(!(s->options & option)) if(!(s->options & option))
s->options |= option; s->options |= option;
updatesfuncs(s); updatesfuncs(s);
} }
/*!\brief désactive une option de la surface */ /*!\brief désactive une option de la surface */
void disable_surface_option(surface_t * s, soptions_t option) { void disable_surface_option(surface_t * s, soptions_t option) {
if(s->options & option) if(s->options & option)
s->options ^= option; s->options ^= option;
updatesfuncs(s); updatesfuncs(s);
} }
/*!\brief créé et renvoie une surface (allouée) à partir de \a n /*!\brief créé et renvoie une surface (allouée) à partir de \a n
@ -74,53 +74,53 @@ void disable_surface_option(surface_t * s, soptions_t option) {
* faux (0) elle force le calcul des normales par triangle et les * faux (0) elle force le calcul des normales par triangle et les
* affecte aux sommets. */ * affecte aux sommets. */
surface_t * new_surface(triangle_t * t, int n, int duplicate_triangles, int has_normals) { surface_t * new_surface(triangle_t * t, int n, int duplicate_triangles, int has_normals) {
const vec4 dcolor = { 0.42f, 0.1f, 0.1f, 1.0f }; const vec4 dcolor = { 0.42f, 0.1f, 0.1f, 1.0f };
surface_t * s = malloc(1 * sizeof *s); surface_t * s = malloc(1 * sizeof *s);
assert(s); assert(s);
s->n = n; s->n = n;
if(duplicate_triangles) { if(duplicate_triangles) {
s->t = malloc(s->n * sizeof *(s->t)); s->t = malloc(s->n * sizeof *(s->t));
assert(s->t); assert(s->t);
memcpy(s->t, t, s->n * sizeof *(s->t)); memcpy(s->t, t, s->n * sizeof *(s->t));
} else } else
s->t = t; s->t = t;
set_diffuse_color(s, dcolor); set_diffuse_color(s, dcolor);
s->options = SO_DEFAULT; s->options = SO_DEFAULT;
s->tex_id = 0; s->tex_id = 0;
updatesfuncs(s); updatesfuncs(s);
if(!has_normals) { if(!has_normals) {
snormals(s); snormals(s);
tnormals2vertices(s); tnormals2vertices(s);
} }
return s; return s;
} }
/*!\brief libère la mémoire utilisée par la surface */ /*!\brief libère la mémoire utilisée par la surface */
void free_surface(surface_t * s) { void free_surface(surface_t * s) {
free(s->t); free(s->t);
free(s); free(s);
} }
/*!\brief charge et fabrique un identifiant pour une texture issue /*!\brief charge et fabrique un identifiant pour une texture issue
* d'un fichier BMP */ * d'un fichier BMP */
GLuint get_texture_from_BMP(const char * filename) { GLuint get_texture_from_BMP(const char * filename) {
GLuint id, old_id; GLuint id, old_id;
/* chargement d'une image dans une surface SDL */ /* chargement d'une image dans une surface SDL */
SDL_Surface * s = SDL_LoadBMP(filename); SDL_Surface * s = SDL_LoadBMP(filename);
assert(s); assert(s);
old_id = gl4dpGetTextureId(); /* au cas où */ old_id = gl4dpGetTextureId(); /* au cas où */
/* création d'un screen GL4Dummies aux dimensions de la texture */ /* création d'un screen GL4Dummies aux dimensions de la texture */
id = gl4dpInitScreenWithDimensions(s->w, s->h); id = gl4dpInitScreenWithDimensions(s->w, s->h);
/* copie de la surface SDL vers le screen en cours */ /* copie de la surface SDL vers le screen en cours */
{ {
GLuint * p = gl4dpGetPixels(); GLuint * p = gl4dpGetPixels();
SDL_Surface * d = SDL_CreateRGBSurface(0, s->w, s->h, 32, R_MASK, G_MASK, B_MASK, A_MASK); SDL_Surface * d = SDL_CreateRGBSurface(0, s->w, s->h, 32, R_MASK, G_MASK, B_MASK, A_MASK);
SDL_BlitSurface(s, NULL, d, NULL); SDL_BlitSurface(s, NULL, d, NULL);
memcpy(p, d->pixels, d->w * d->h * sizeof *p); memcpy(p, d->pixels, d->w * d->h * sizeof *p);
SDL_FreeSurface(d); SDL_FreeSurface(d);
} }
/* libération de la surface SDL */ /* libération de la surface SDL */
SDL_FreeSurface(s); SDL_FreeSurface(s);
if(old_id) if(old_id)
gl4dpSetScreen(old_id); gl4dpSetScreen(old_id);
return id; return id;
} }

View file

@ -20,59 +20,59 @@ static inline void clip2_unit_cube(triangle_t * t);
matrice de model-view \a model_view_matrix et de projection \a projection_matrix. \a matrice de model-view \a model_view_matrix et de projection \a projection_matrix. \a
ti_model_view_matrix est la transposée de l'inverse de la matrice \a model_view_matrix.*/ ti_model_view_matrix est la transposée de l'inverse de la matrice \a model_view_matrix.*/
vertex_t vtransform(surface_t * s, vertex_t v, float * model_view_matrix, float * ti_model_view_matrix, float * projection_matrix, float * viewport) { vertex_t vtransform(surface_t * s, vertex_t v, float * model_view_matrix, float * ti_model_view_matrix, float * projection_matrix, float * viewport) {
float dist = 1.0f; float dist = 1.0f;
vec4 r1, r2; vec4 r1, r2;
v.state = PS_NONE; v.state = PS_NONE;
MMAT4XVEC4((float *)&r1, model_view_matrix, (float *)&(v.position)); MMAT4XVEC4((float *)&r1, model_view_matrix, (float *)&(v.position));
MMAT4XVEC4((float *)&r2, projection_matrix, (float *)&r1); MMAT4XVEC4((float *)&r2, projection_matrix, (float *)&r1);
r2.x /= r2.w; r2.x /= r2.w;
r2.y /= r2.w; r2.y /= r2.w;
r2.z /= r2.w; r2.z /= r2.w;
r2.w = 1.0f; r2.w = 1.0f;
/* dist doit être à 1 ci-après */ /* dist doit être à 1 ci-après */
if(r2.x < -dist) v.state |= PS_OUT_LEFT; if(r2.x < -dist) v.state |= PS_OUT_LEFT;
if(r2.x > dist) v.state |= PS_OUT_RIGHT; if(r2.x > dist) v.state |= PS_OUT_RIGHT;
if(r2.y < -dist) v.state |= PS_OUT_BOTTOM; if(r2.y < -dist) v.state |= PS_OUT_BOTTOM;
if(r2.y > dist) v.state |= PS_OUT_TOP; if(r2.y > dist) v.state |= PS_OUT_TOP;
if(r2.z < -dist) v.state |= PS_OUT_NEAR; if(r2.z < -dist) v.state |= PS_OUT_NEAR;
if(r2.z > dist) v.state |= PS_OUT_FAR; if(r2.z > dist) v.state |= PS_OUT_FAR;
/* "hack" pas terrible permettant d'éviter les gros triangles /* "hack" pas terrible permettant d'éviter les gros triangles
partiellement hors-champ. Modifier dist pour jouer sur la taille partiellement hors-champ. Modifier dist pour jouer sur la taille
(une fois projetés) des triangles qu'on laisse passer (plus c'est (une fois projetés) des triangles qu'on laisse passer (plus c'est
gros plus c'est lent avec les gros triangles). La "vraie" gros plus c'est lent avec les gros triangles). La "vraie"
solution est obtenue en calculant l'intersection exacte entre le solution est obtenue en calculant l'intersection exacte entre le
triangle et le cube unitaire ; attention, ceci produit triangle et le cube unitaire ; attention, ceci produit
potentiellement une nouvelle liste de triangles à chaque frame, potentiellement une nouvelle liste de triangles à chaque frame,
et les attributs des sommets doivent être recalculés. */ et les attributs des sommets doivent être recalculés. */
dist = 10.0f; dist = 10.0f;
if(r2.x < -dist || r2.x > dist || r2.y < -dist || r2.y > dist || r2.z < -dist || r2.z > dist) { if(r2.x < -dist || r2.x > dist || r2.y < -dist || r2.y > dist || r2.z < -dist || r2.z > dist) {
v.state |= PS_TOO_FAR; v.state |= PS_TOO_FAR;
return v;
}
/* Gouraud */
if(s->options & SO_USE_LIGHTING) {
/* la lumière est positionnelle et fixe dans la scène. \todo dans
scene.c la rendre modifiable, voire aussi pouvoir la placer par
rapport aux objets (elle subirait la matrice modèle). */
const vec4 lp[1] = { {0.0f, 0.0f, 1.0f} };
vec4 ld = {lp[0].x - r1.x, lp[0].y - r1.y, lp[0].z - r1.z, lp[0].w - r1.w};
float n[4] = {v.normal.x, v.normal.y, v.normal.z, 0.0f}, res[4];
MMAT4XVEC4(res, ti_model_view_matrix, n);
MVEC3NORMALIZE(res);
MVEC3NORMALIZE((float *)&ld);
v.li = MVEC3DOT(res, (float *)&ld);
v.li = MIN(MAX(0.0f, v.li), 1.0f);
} else
v.li = 1.0f;
v.icolor = v.color0;
/* Mapping du cube unitaire vers l'écran */
v.x = viewport[0] + ((r2.x + 1.0f) * 0.5f) * (viewport[2] - EPSILON);
v.y = viewport[1] + ((r2.y + 1.0f) * 0.5f) * (viewport[3] - EPSILON);
v.z = pow((-r2.z + 1.0f) * 0.5f, 0.5);
/* sinon pour near = 0.1f et far = 10.0f on peut rendre non linéaire la depth avec */
/* v.z = 1.0f - (1.0f / r2.z - 1.0f / 0.1f) / (1.0f / 10.0f - 1.0f / 0.1f); */
v.zmod = r1.z;
return v; return v;
}
/* Gouraud */
if(s->options & SO_USE_LIGHTING) {
/* la lumière est positionnelle et fixe dans la scène. \todo dans
scene.c la rendre modifiable, voire aussi pouvoir la placer par
rapport aux objets (elle subirait la matrice modèle). */
const vec4 lp[1] = { {0.0f, 0.0f, 1.0f} };
vec4 ld = {lp[0].x - r1.x, lp[0].y - r1.y, lp[0].z - r1.z, lp[0].w - r1.w};
float n[4] = {v.normal.x, v.normal.y, v.normal.z, 0.0f}, res[4];
MMAT4XVEC4(res, ti_model_view_matrix, n);
MVEC3NORMALIZE(res);
MVEC3NORMALIZE((float *)&ld);
v.li = MVEC3DOT(res, (float *)&ld);
v.li = MIN(MAX(0.0f, v.li), 1.0f);
} else
v.li = 1.0f;
v.icolor = v.color0;
/* Mapping du cube unitaire vers l'écran */
v.x = viewport[0] + ((r2.x + 1.0f) * 0.5f) * (viewport[2] - EPSILON);
v.y = viewport[1] + ((r2.y + 1.0f) * 0.5f) * (viewport[3] - EPSILON);
v.z = pow((-r2.z + 1.0f) * 0.5f, 0.5);
/* sinon pour near = 0.1f et far = 10.0f on peut rendre non linéaire la depth avec */
/* v.z = 1.0f - (1.0f / r2.z - 1.0f / 0.1f) / (1.0f / 10.0f - 1.0f / 0.1f); */
v.zmod = r1.z;
return v;
} }
/*!\brief projette le triangle \a t à l'écran (\a W x \a H) selon la /*!\brief projette le triangle \a t à l'écran (\a W x \a H) selon la
@ -86,128 +86,128 @@ vertex_t vtransform(surface_t * s, vertex_t v, float * model_view_matrix, float
* \see clip2_unit_cube * \see clip2_unit_cube
*/ */
void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport) { void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport) {
int i, j; int i, j;
float ti_model_view_matrix[16]; float ti_model_view_matrix[16];
triangle_t vcull; triangle_t vcull;
/* calcul de la transposée de l'inverse de la matrice model-view /* calcul de la transposée de l'inverse de la matrice model-view
pour la transformation des normales et le calcul du lambertien pour la transformation des normales et le calcul du lambertien
utilisé par le shading Gouraud dans vtransform. */ utilisé par le shading Gouraud dans vtransform. */
memcpy(ti_model_view_matrix, model_view_matrix, sizeof ti_model_view_matrix); memcpy(ti_model_view_matrix, model_view_matrix, sizeof ti_model_view_matrix);
MMAT4INVERSE(ti_model_view_matrix); MMAT4INVERSE(ti_model_view_matrix);
MMAT4TRANSPOSE(ti_model_view_matrix); MMAT4TRANSPOSE(ti_model_view_matrix);
for(i = 0; i < s->n; ++i) { for(i = 0; i < s->n; ++i) {
s->t[i].state = PS_NONE; s->t[i].state = PS_NONE;
for(j = 0; j < 3; ++j) { for(j = 0; j < 3; ++j) {
s->t[i].v[j] = vtransform(s, s->t[i].v[j], model_view_matrix, ti_model_view_matrix, projection_matrix, viewport); s->t[i].v[j] = vtransform(s, s->t[i].v[j], model_view_matrix, ti_model_view_matrix, projection_matrix, viewport);
if(s->options & SO_CULL_BACKFACES) { if(s->options & SO_CULL_BACKFACES) {
vcull.v[j].position.x = s->t[i].v[j].x; vcull.v[j].position.x = s->t[i].v[j].x;
vcull.v[j].position.y = s->t[i].v[j].y; vcull.v[j].position.y = s->t[i].v[j].y;
vcull.v[j].position.z = 0.0f; vcull.v[j].position.z = 0.0f;
} }
}
if(s->options & SO_CULL_BACKFACES) {
tnormal(&vcull);
if(vcull.normal.z <= 0.0f) {
s->t[i].state |= PS_CULL;
continue;
}
}
clip2_unit_cube(&(s->t[i]));
} }
if(s->options & SO_CULL_BACKFACES) {
tnormal(&vcull);
if(vcull.normal.z <= 0.0f) {
s->t[i].state |= PS_CULL;
continue;
}
}
clip2_unit_cube(&(s->t[i]));
}
} }
/*!\brief multiplie deux matrices : \a res = \a res x \a m */ /*!\brief multiplie deux matrices : \a res = \a res x \a m */
void mult_matrix(float * res, float * m) { void mult_matrix(float * res, float * m) {
/* res = res x m */ /* res = res x m */
float cpy[16]; float cpy[16];
memcpy(cpy, res, sizeof cpy); memcpy(cpy, res, sizeof cpy);
MMAT4XMAT4(res, cpy, m); MMAT4XMAT4(res, cpy, m);
} }
/*!\brief ajoute (multiplication droite) une translation à la matrice /*!\brief ajoute (multiplication droite) une translation à la matrice
* \a m */ * \a m */
void translate(float * m, float tx, float ty, float tz) { void translate(float * m, float tx, float ty, float tz) {
float mat[] = { 1.0f, 0.0f, 0.0f, tx, float mat[] = { 1.0f, 0.0f, 0.0f, tx,
0.0f, 1.0f, 0.0f, ty, 0.0f, 1.0f, 0.0f, ty,
0.0f, 0.0f, 1.0f, tz, 0.0f, 0.0f, 1.0f, tz,
0.0f, 0.0f, 0.0f, 1.0f }; 0.0f, 0.0f, 0.0f, 1.0f };
mult_matrix(m, mat); mult_matrix(m, mat);
} }
/*!\brief ajoute (multiplication droite) une rotation à la matrice \a /*!\brief ajoute (multiplication droite) une rotation à la matrice \a
* m */ * m */
void rotate(float * m, float angle, float x, float y, float z) { void rotate(float * m, float angle, float x, float y, float z) {
float n = sqrtf(x * x + y * y + z * z); float n = sqrtf(x * x + y * y + z * z);
if ( n > 0.0f ) { if ( n > 0.0f ) {
float a, s, c, cc, x2, y2, z2, xy, yz, zx, xs, ys, zs; float a, s, c, cc, x2, y2, z2, xy, yz, zx, xs, ys, zs;
float mat[] = { 0.0f, 0.0f, 0.0f, 0.0f, float mat[] = { 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f }; 0.0f, 0.0f, 0.0f, 1.0f };
s = sinf ( a = (angle * (float)M_PI / 180.0f) ); s = sinf ( a = (angle * (float)M_PI / 180.0f) );
cc = 1.0f - (c = cosf ( a )); cc = 1.0f - (c = cosf ( a ));
x /= n; y /= n; z /= n; x /= n; y /= n; z /= n;
x2 = x * x; y2 = y * y; z2 = z * z; x2 = x * x; y2 = y * y; z2 = z * z;
xy = x * y; yz = y * z; zx = z * x; xy = x * y; yz = y * z; zx = z * x;
xs = x * s; ys = y * s; zs = z * s; xs = x * s; ys = y * s; zs = z * s;
mat[0] = (cc * x2) + c; mat[0] = (cc * x2) + c;
mat[1] = (cc * xy) - zs; mat[1] = (cc * xy) - zs;
mat[2] = (cc * zx) + ys; mat[2] = (cc * zx) + ys;
/* mat[3] = 0.0f; */ /* mat[3] = 0.0f; */
mat[4] = (cc * xy) + zs; mat[4] = (cc * xy) + zs;
mat[5] = (cc * y2) + c; mat[5] = (cc * y2) + c;
mat[6] = (cc * yz) - xs; mat[6] = (cc * yz) - xs;
/* mat[7] = 0.0f; */ /* mat[7] = 0.0f; */
mat[8] = (cc * zx) - ys; mat[8] = (cc * zx) - ys;
mat[9] = (cc * yz) + xs; mat[9] = (cc * yz) + xs;
mat[10] = (cc * z2) + c; mat[10] = (cc * z2) + c;
/* mat[11] = 0.0f; */ /* mat[11] = 0.0f; */
/* mat[12] = 0.0f; mat[= 0.0f; mat[14] = 0.0f; mat[15] = 1.0f; */ /* mat[12] = 0.0f; mat[= 0.0f; mat[14] = 0.0f; mat[15] = 1.0f; */
mult_matrix(m, mat); mult_matrix(m, mat);
} }
} }
/*!\brief ajoute (multiplication droite) un scale à la matrice \a m */ /*!\brief ajoute (multiplication droite) un scale à la matrice \a m */
void scale(float * m, float sx, float sy, float sz) { void scale(float * m, float sx, float sy, float sz) {
float mat[] = { sx , 0.0f, 0.0f, 0.0f, float mat[] = { sx , 0.0f, 0.0f, 0.0f,
0.0f, sy, 0.0f, 0.0f, 0.0f, sy, 0.0f, 0.0f,
0.0f, 0.0f, sz, 0.0f, 0.0f, 0.0f, sz, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f }; 0.0f, 0.0f, 0.0f, 1.0f };
mult_matrix(m, mat); mult_matrix(m, mat);
} }
/*!\brief simule une free camera, voir la doc de gluLookAt */ /*!\brief simule une free camera, voir la doc de gluLookAt */
void lookAt(float * m, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) { void lookAt(float * m, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) {
float forward[3], side[3], up[3]; float forward[3], side[3], up[3];
float mat[] = { float mat[] = {
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f 0.0f, 0.0f, 0.0f, 1.0f
}; };
forward[0] = centerX - eyeX; forward[0] = centerX - eyeX;
forward[1] = centerY - eyeY; forward[1] = centerY - eyeY;
forward[2] = centerZ - eyeZ; forward[2] = centerZ - eyeZ;
up[0] = upX; up[0] = upX;
up[1] = upY; up[1] = upY;
up[2] = upZ; up[2] = upZ;
MVEC3NORMALIZE(forward); MVEC3NORMALIZE(forward);
/* side = forward x up */ /* side = forward x up */
MVEC3CROSS(side, forward, up); MVEC3CROSS(side, forward, up);
MVEC3NORMALIZE(side); MVEC3NORMALIZE(side);
/* up = side x forward */ /* up = side x forward */
MVEC3CROSS(up, side, forward); MVEC3CROSS(up, side, forward);
mat[0] = side[0]; mat[0] = side[0];
mat[1] = side[1]; mat[1] = side[1];
mat[2] = side[2]; mat[2] = side[2];
mat[4] = up[0]; mat[4] = up[0];
mat[5] = up[1]; mat[5] = up[1];
mat[6] = up[2]; mat[6] = up[2];
mat[8] = -forward[0]; mat[8] = -forward[0];
mat[9] = -forward[1]; mat[9] = -forward[1];
mat[10] = -forward[2]; mat[10] = -forward[2];
mult_matrix(m, mat); mult_matrix(m, mat);
translate(m, -eyeX, -eyeY, -eyeZ); translate(m, -eyeX, -eyeY, -eyeZ);
} }
/*!\brief intersection triangle-cube unitaire, à compléter (voir le /*!\brief intersection triangle-cube unitaire, à compléter (voir le
@ -215,18 +215,18 @@ void lookAt(float * m, float eyeX, float eyeY, float eyeZ, float centerX, float
void clip2_unit_cube(triangle_t * t) { void clip2_unit_cube(triangle_t * t) {
int i, oleft = 0, oright = 0, obottom = 0, otop = 0, onear = 0, ofar = 0; int i, oleft = 0, oright = 0, obottom = 0, otop = 0, onear = 0, ofar = 0;
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
if(t->v[i].state & PS_OUT_LEFT) ++oleft; if(t->v[i].state & PS_OUT_LEFT) ++oleft;
if(t->v[i].state & PS_OUT_RIGHT) ++oright; if(t->v[i].state & PS_OUT_RIGHT) ++oright;
if(t->v[i].state & PS_OUT_BOTTOM) ++obottom; if(t->v[i].state & PS_OUT_BOTTOM) ++obottom;
if(t->v[i].state & PS_OUT_TOP) ++otop; if(t->v[i].state & PS_OUT_TOP) ++otop;
if(t->v[i].state & PS_OUT_NEAR) ++onear; if(t->v[i].state & PS_OUT_NEAR) ++onear;
if(t->v[i].state & PS_OUT_FAR) ++ofar; if(t->v[i].state & PS_OUT_FAR) ++ofar;
} }
if(!(oleft | oright | obottom | otop | onear | ofar)) if(!(oleft | oright | obottom | otop | onear | ofar))
return; return;
if(oleft == 3 || oright == 3 || obottom == 3 || otop == 3 || onear == 3 || ofar == 3) { if(oleft == 3 || oright == 3 || obottom == 3 || otop == 3 || onear == 3 || ofar == 3) {
t->state |= PS_TOTALLY_OUT; t->state |= PS_TOTALLY_OUT;
return; return;
} }
t->state |= PS_PARTIALLY_OUT; t->state |= PS_PARTIALLY_OUT;
/* le cas PARTIALLY_OUT n'est pas réellement géré. Il serait /* le cas PARTIALLY_OUT n'est pas réellement géré. Il serait

300
window.c
View file

@ -42,172 +42,172 @@ static float _ycam = 3.0f;
/*!\brief paramètre l'application et lance la boucle infinie. */ /*!\brief paramètre l'application et lance la boucle infinie. */
int main(int argc, char ** argv) { int main(int argc, char ** argv) {
/* tentative de création d'une fenêtre pour GL4Dummies */ /* tentative de création d'une fenêtre pour GL4Dummies */
if(!gl4duwCreateWindow(argc, argv, /* args du programme */ if(!gl4duwCreateWindow(argc, argv, /* args du programme */
"The DIY Rasterizer", /* titre */ "The DIY Rasterizer", /* titre */
10, 10, 800, 600, /* x, y, largeur, heuteur */ 10, 10, 800, 600, /* x, y, largeur, heuteur */
GL4DW_SHOWN) /* état visible */) { GL4DW_SHOWN) /* état visible */) {
/* ici si échec de la création souvent lié à un problème d'absence /* ici si échec de la création souvent lié à un problème d'absence
* de contexte graphique ou d'impossibilité d'ouverture d'un * de contexte graphique ou d'impossibilité d'ouverture d'un
* contexte OpenGL (au moins 3.2) */ * contexte OpenGL (au moins 3.2) */
return 1; return 1;
} }
init(); init();
/* mettre en place la fonction d'interception clavier */ /* mettre en place la fonction d'interception clavier */
gl4duwKeyDownFunc(key); gl4duwKeyDownFunc(key);
/* mettre en place la fonction de display */ /* mettre en place la fonction de display */
gl4duwDisplayFunc(draw); gl4duwDisplayFunc(draw);
/* boucle infinie pour éviter que le programme ne s'arrête et ferme /* boucle infinie pour éviter que le programme ne s'arrête et ferme
* la fenêtre immédiatement */ * la fenêtre immédiatement */
gl4duwMainLoop(); gl4duwMainLoop();
return 0; return 0;
} }
/*!\brief init de nos données, spécialement les trois surfaces /*!\brief init de nos données, spécialement les trois surfaces
* utilisées dans ce code */ * utilisées dans ce code */
void init(void) { void init(void) {
GLuint id; GLuint id;
vec4 r = {1, 0, 0, 1}, g = {0, 1, 0, 1}, b = {0, 0, 1, 1}; vec4 r = {1, 0, 0, 1}, g = {0, 1, 0, 1}, b = {0, 0, 1, 1};
/* création d'un screen GL4Dummies (texture dans laquelle nous /* création d'un screen GL4Dummies (texture dans laquelle nous
* pouvons dessiner) aux dimensions de la fenêtre. IMPORTANT de * pouvons dessiner) aux dimensions de la fenêtre. IMPORTANT de
* créer le screen avant d'utiliser les fonctions liées au * créer le screen avant d'utiliser les fonctions liées au
* textures */ * textures */
gl4dpInitScreen(); gl4dpInitScreen();
/* Pour forcer la désactivation de la synchronisation verticale */ /* Pour forcer la désactivation de la synchronisation verticale */
SDL_GL_SetSwapInterval(0); SDL_GL_SetSwapInterval(0);
/* on créé nos trois type de surfaces */ /* on créé nos trois type de surfaces */
_quad = mk_quad(); /* ça fait 2 triangles */ _quad = mk_quad(); /* ça fait 2 triangles */
_cube = mk_cube(); /* ça fait 2x6 triangles */ _cube = mk_cube(); /* ça fait 2x6 triangles */
_sphere = mk_sphere(12, 12); /* ça fait 12x12x2 trianles ! */ _sphere = mk_sphere(12, 12); /* ça fait 12x12x2 trianles ! */
/* on change les couleurs de surfaces */ /* on change les couleurs de surfaces */
_quad->dcolor = r; _cube->dcolor = b; _sphere->dcolor = g; _quad->dcolor = r; _cube->dcolor = b; _sphere->dcolor = g;
/* on leur rajoute à toutes la même texture */ /* on leur rajoute à toutes la même texture */
id = get_texture_from_BMP("images/tex.bmp"); id = get_texture_from_BMP("images/tex.bmp");
set_texture_id( _quad, id); set_texture_id( _quad, id);
set_texture_id( _cube, id); set_texture_id( _cube, id);
set_texture_id(_sphere, id); set_texture_id(_sphere, id);
/* si _use_tex != 0, on active l'utilisation de la texture pour les /* si _use_tex != 0, on active l'utilisation de la texture pour les
* trois */ * trois */
if(_use_tex) { if(_use_tex) {
enable_surface_option( _quad, SO_USE_TEXTURE); enable_surface_option( _quad, SO_USE_TEXTURE);
enable_surface_option( _cube, SO_USE_TEXTURE); enable_surface_option( _cube, SO_USE_TEXTURE);
enable_surface_option(_sphere, SO_USE_TEXTURE); enable_surface_option(_sphere, SO_USE_TEXTURE);
} }
/* si _use_lighting != 0, on active l'ombrage */ /* si _use_lighting != 0, on active l'ombrage */
if(_use_lighting) { if(_use_lighting) {
enable_surface_option( _quad, SO_USE_LIGHTING); enable_surface_option( _quad, SO_USE_LIGHTING);
enable_surface_option( _cube, SO_USE_LIGHTING); enable_surface_option( _cube, SO_USE_LIGHTING);
enable_surface_option(_sphere, SO_USE_LIGHTING); enable_surface_option(_sphere, SO_USE_LIGHTING);
} }
/* on désactive le back cull face pour le quadrilatère, ainsi on /* on désactive le back cull face pour le quadrilatère, ainsi on
* peut voir son arrière quand le lighting est inactif */ * peut voir son arrière quand le lighting est inactif */
disable_surface_option(_quad, SO_CULL_BACKFACES); disable_surface_option(_quad, SO_CULL_BACKFACES);
/* mettre en place la fonction à appeler en cas de sortie */ /* mettre en place la fonction à appeler en cas de sortie */
atexit(sortie); atexit(sortie);
} }
/*!\brief la fonction appelée à chaque display. */ /*!\brief la fonction appelée à chaque display. */
void draw(void) { void draw(void) {
static float a = 0.0f; static float a = 0.0f;
float model_view_matrix[16], projection_matrix[16], nmv[16]; float model_view_matrix[16], projection_matrix[16], nmv[16];
/* effacer l'écran et le buffer de profondeur */ /* effacer l'écran et le buffer de profondeur */
gl4dpClearScreen(); gl4dpClearScreen();
clear_depth_map(); clear_depth_map();
/* des macros facilitant le travail avec des matrices et des /* des macros facilitant le travail avec des matrices et des
* vecteurs se trouvent dans la bibliothèque GL4Dummies, dans le * vecteurs se trouvent dans la bibliothèque GL4Dummies, dans le
* fichier gl4dm.h */ * fichier gl4dm.h */
/* charger un frustum dans projection_matrix */ /* charger un frustum dans projection_matrix */
MFRUSTUM(projection_matrix, -0.05f, 0.05f, -0.05f, 0.05f, 0.1f, 1000.0f); MFRUSTUM(projection_matrix, -0.05f, 0.05f, -0.05f, 0.05f, 0.1f, 1000.0f);
/* charger la matrice identité dans model-view */ /* charger la matrice identité dans model-view */
MIDENTITY(model_view_matrix); MIDENTITY(model_view_matrix);
/* on place la caméra en arrière-haut, elle regarde le centre de la scène */ /* on place la caméra en arrière-haut, elle regarde le centre de la scène */
lookAt(model_view_matrix, 0, _ycam, 10, 0, 0, 0, 0, 1, 0); lookAt(model_view_matrix, 0, _ycam, 10, 0, 0, 0, 0, 1, 0);
/* le quadrilatère est mis à gauche et tourne autour de son axe x */ /* le quadrilatère est mis à gauche et tourne autour de son axe x */
memcpy(nmv, model_view_matrix, sizeof nmv); /* copie model_view_matrix dans nmv */ memcpy(nmv, model_view_matrix, sizeof nmv); /* copie model_view_matrix dans nmv */
translate(nmv, -3.0f, 0.0f, 0.0f); translate(nmv, -3.0f, 0.0f, 0.0f);
rotate(nmv, a, 1.0f, 0.0f, 0.0f); rotate(nmv, a, 1.0f, 0.0f, 0.0f);
transform_n_rasterize(_quad, nmv, projection_matrix); transform_n_rasterize(_quad, nmv, projection_matrix);
/* le cube est mis à droite et tourne autour de son axe z */ /* le cube est mis à droite et tourne autour de son axe z */
memcpy(nmv, model_view_matrix, sizeof nmv); /* copie model_view_matrix dans nmv */ memcpy(nmv, model_view_matrix, sizeof nmv); /* copie model_view_matrix dans nmv */
translate(nmv, 3.0f, 0.0f, 0.0f); translate(nmv, 3.0f, 0.0f, 0.0f);
rotate(nmv, a, 0.0f, 0.0f, 1.0f); rotate(nmv, a, 0.0f, 0.0f, 1.0f);
transform_n_rasterize(_cube, nmv, projection_matrix); transform_n_rasterize(_cube, nmv, projection_matrix);
/* la sphère est laissée au centre et tourne autour de son axe y */ /* la sphère est laissée au centre et tourne autour de son axe y */
memcpy(nmv, model_view_matrix, sizeof nmv); /* copie model_view_matrix dans nmv */ memcpy(nmv, model_view_matrix, sizeof nmv); /* copie model_view_matrix dans nmv */
rotate(nmv, a, 0.0f, 1.0f, 0.0f); rotate(nmv, a, 0.0f, 1.0f, 0.0f);
transform_n_rasterize(_sphere, nmv, projection_matrix); transform_n_rasterize(_sphere, nmv, projection_matrix);
/* déclarer qu'on a changé des pixels du screen (en bas niveau) */ /* déclarer qu'on a changé des pixels du screen (en bas niveau) */
gl4dpScreenHasChanged(); gl4dpScreenHasChanged();
/* fonction permettant de raffraîchir l'ensemble de la fenêtre*/ /* fonction permettant de raffraîchir l'ensemble de la fenêtre*/
gl4dpUpdateScreen(NULL); gl4dpUpdateScreen(NULL);
a += 0.1f; a += 0.1f;
} }
/*!\brief intercepte l'événement clavier pour modifier les options. */ /*!\brief intercepte l'événement clavier pour modifier les options. */
void key(int keycode) { void key(int keycode) {
switch(keycode) { switch(keycode) {
case GL4DK_UP: case GL4DK_UP:
_ycam += 0.05f; _ycam += 0.05f;
break; break;
case GL4DK_DOWN: case GL4DK_DOWN:
_ycam -= 0.05f; _ycam -= 0.05f;
break; break;
case GL4DK_t: /* 't' la texture */ case GL4DK_t: /* 't' la texture */
_use_tex = !_use_tex; _use_tex = !_use_tex;
if(_use_tex) { if(_use_tex) {
enable_surface_option( _quad, SO_USE_TEXTURE); enable_surface_option( _quad, SO_USE_TEXTURE);
enable_surface_option( _cube, SO_USE_TEXTURE); enable_surface_option( _cube, SO_USE_TEXTURE);
enable_surface_option(_sphere, SO_USE_TEXTURE); enable_surface_option(_sphere, SO_USE_TEXTURE);
} else { } else {
disable_surface_option( _quad, SO_USE_TEXTURE); disable_surface_option( _quad, SO_USE_TEXTURE);
disable_surface_option( _cube, SO_USE_TEXTURE); disable_surface_option( _cube, SO_USE_TEXTURE);
disable_surface_option(_sphere, SO_USE_TEXTURE); disable_surface_option(_sphere, SO_USE_TEXTURE);
}
break;
case GL4DK_c: /* 'c' utiliser la couleur */
_use_color = !_use_color;
if(_use_color) {
enable_surface_option( _quad, SO_USE_COLOR);
enable_surface_option( _cube, SO_USE_COLOR);
enable_surface_option(_sphere, SO_USE_COLOR);
} else {
disable_surface_option( _quad, SO_USE_COLOR);
disable_surface_option( _cube, SO_USE_COLOR);
disable_surface_option(_sphere, SO_USE_COLOR);
}
break;
case GL4DK_l: /* 'l' utiliser l'ombrage par la méthode Gouraud */
_use_lighting = !_use_lighting;
if(_use_lighting) {
enable_surface_option( _quad, SO_USE_LIGHTING);
enable_surface_option( _cube, SO_USE_LIGHTING);
enable_surface_option(_sphere, SO_USE_LIGHTING);
} else {
disable_surface_option( _quad, SO_USE_LIGHTING);
disable_surface_option( _cube, SO_USE_LIGHTING);
disable_surface_option(_sphere, SO_USE_LIGHTING);
}
break;
default: break;
} }
break;
case GL4DK_c: /* 'c' utiliser la couleur */
_use_color = !_use_color;
if(_use_color) {
enable_surface_option( _quad, SO_USE_COLOR);
enable_surface_option( _cube, SO_USE_COLOR);
enable_surface_option(_sphere, SO_USE_COLOR);
} else {
disable_surface_option( _quad, SO_USE_COLOR);
disable_surface_option( _cube, SO_USE_COLOR);
disable_surface_option(_sphere, SO_USE_COLOR);
}
break;
case GL4DK_l: /* 'l' utiliser l'ombrage par la méthode Gouraud */
_use_lighting = !_use_lighting;
if(_use_lighting) {
enable_surface_option( _quad, SO_USE_LIGHTING);
enable_surface_option( _cube, SO_USE_LIGHTING);
enable_surface_option(_sphere, SO_USE_LIGHTING);
} else {
disable_surface_option( _quad, SO_USE_LIGHTING);
disable_surface_option( _cube, SO_USE_LIGHTING);
disable_surface_option(_sphere, SO_USE_LIGHTING);
}
break;
default: break;
}
} }
/*!\brief à appeler à la sortie du programme. */ /*!\brief à appeler à la sortie du programme. */
void sortie(void) { void sortie(void) {
/* on libère nos trois surfaces */ /* on libère nos trois surfaces */
if(_quad) { if(_quad) {
free_surface(_quad); free_surface(_quad);
_quad = NULL; _quad = NULL;
} }
if(_cube) { if(_cube) {
free_surface(_cube); free_surface(_cube);
_cube = NULL; _cube = NULL;
} }
if(_sphere) { if(_sphere) {
free_surface(_sphere); free_surface(_sphere);
_sphere = NULL; _sphere = NULL;
} }
/* libère tous les objets produits par GL4Dummies, ici /* libère tous les objets produits par GL4Dummies, ici
* principalement les screen */ * principalement les screen */
gl4duClean(GL4DU_ALL); gl4duClean(GL4DU_ALL);
} }