trim spaces and use 4 space instead of 2
This commit is contained in:
parent
db59cc2a85
commit
0b62517c35
6 changed files with 894 additions and 893 deletions
252
geometry.c
252
geometry.c
|
@ -1,10 +1,10 @@
|
||||||
/*!\file geometry.h
|
/*!\file geometry.h
|
||||||
*
|
*
|
||||||
* \brief quelques surfaces basiques sous forme polygonale : un plan
|
* \brief quelques surfaces basiques sous forme polygonale : un plan
|
||||||
* (quad), un cube et une sphere.
|
* (quad), un cube et une sphere.
|
||||||
*
|
*
|
||||||
* \author Farès BELHADJ, amsi@up8.edu
|
* \author Farès BELHADJ, amsi@up8.edu
|
||||||
* \date November, 2021.
|
* \date November, 2021.
|
||||||
*/
|
*/
|
||||||
#include "rasterize.h"
|
#include "rasterize.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
581
rasterize.c
581
rasterize.c
|
@ -3,7 +3,7 @@
|
||||||
* principalement que du cas du triangle.
|
* principalement que du cas du triangle.
|
||||||
*
|
*
|
||||||
* CE CODE A EU COMME POINT DE DÉPART CE QUI A ÉTÉ FAIT
|
* CE CODE A EU COMME POINT DE DÉPART CE QUI A ÉTÉ FAIT
|
||||||
* EN COURS, IL EST COMPLÉTÉ PAR L'ENSEIGNANT POUR ÊTRE
|
* EN COURS, IL EST COMPLÉTÉ PAR L'ENSEIGNANT POUR ÊTRE
|
||||||
* FONCTIONNEL MAIS IL DES CHOSES À AMÉLIORER.
|
* FONCTIONNEL MAIS IL DES CHOSES À AMÉLIORER.
|
||||||
*
|
*
|
||||||
* \author Farès BELHADJ, amsi@up8.edu
|
* \author Farès BELHADJ, amsi@up8.edu
|
||||||
|
@ -33,7 +33,7 @@ static inline GLubyte red(GLuint c);
|
||||||
static inline GLubyte green(GLuint c);
|
static inline GLubyte green(GLuint c);
|
||||||
static inline GLubyte blue(GLuint c);
|
static inline GLubyte blue(GLuint c);
|
||||||
static inline GLubyte alpha(GLuint c);
|
static inline GLubyte alpha(GLuint c);
|
||||||
static void pquit(void);
|
static void pquit(void);
|
||||||
|
|
||||||
/*!\brief la texture courante à utiliser en cas de mapping de texture */
|
/*!\brief la texture courante à utiliser en cas de mapping de texture */
|
||||||
static GLuint * _tex = NULL;
|
static GLuint * _tex = NULL;
|
||||||
|
@ -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,331 +126,331 @@ 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)
|
||||||
* de la structure vertex_t en utilisant \a a et \a b, les
|
* de la structure vertex_t en utilisant \a a et \a b, les
|
||||||
* facteurs \a fa et \a fb, le tout dans \a r
|
* facteurs \a fa et \a fb, le tout dans \a r
|
||||||
* \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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
208
rasterize.h
208
rasterize.h
|
@ -1,10 +1,10 @@
|
||||||
/*!\file rasterize.h
|
/*!\file rasterize.h
|
||||||
*
|
*
|
||||||
* \brief structures de données et protos de fonctions externes pour
|
* \brief structures de données et protos de fonctions externes pour
|
||||||
* réaliser un moteur de rendu DIY par rastérisation.
|
* réaliser un moteur de rendu DIY par rastérisation.
|
||||||
*
|
*
|
||||||
* \author Farès BELHADJ, amsi@up8.edu
|
* \author Farès BELHADJ, amsi@up8.edu
|
||||||
* \date November 17, 2021.
|
* \date November 17, 2021.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RASTERIZE_H_SEEN
|
#ifndef RASTERIZE_H_SEEN
|
||||||
|
@ -19,72 +19,72 @@
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
typedef enum pstate_t pstate_t;
|
|
||||||
typedef enum soptions_t soptions_t;
|
|
||||||
typedef struct vec4 vec4;
|
|
||||||
typedef struct vec3 vec3;
|
|
||||||
typedef struct vec2 vec2;
|
|
||||||
typedef struct vertex_t vertex_t;
|
|
||||||
typedef struct triangle_t triangle_t;
|
|
||||||
typedef struct surface_t surface_t;
|
|
||||||
|
|
||||||
/*!\brief états pour les sommets ou les triangles */
|
typedef enum pstate_t pstate_t;
|
||||||
enum pstate_t {
|
typedef enum soptions_t soptions_t;
|
||||||
PS_NONE = 0,
|
typedef struct vec4 vec4;
|
||||||
PS_TOTALLY_OUT = 1,
|
typedef struct vec3 vec3;
|
||||||
PS_PARTIALLY_OUT = 2,
|
typedef struct vec2 vec2;
|
||||||
PS_CULL = 4, /* si en BACKFACE et que
|
typedef struct vertex_t vertex_t;
|
||||||
SO_CULL_BACKFACES est actif */
|
typedef struct triangle_t triangle_t;
|
||||||
PS_TOO_FAR = 8,
|
typedef struct surface_t surface_t;
|
||||||
PS_OUT_LEFT = 16,
|
|
||||||
PS_OUT_RIGHT = 32,
|
|
||||||
PS_OUT_BOTTOM = 64,
|
|
||||||
PS_OUT_TOP = 128,
|
|
||||||
PS_OUT_NEAR = 256,
|
|
||||||
PS_OUT_FAR = 512
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!\brief options pour les surfaces */
|
/*!\brief états pour les sommets ou les triangles */
|
||||||
enum soptions_t {
|
enum pstate_t {
|
||||||
SO_NONE = 0, /* la surface n'a pas de rendu
|
PS_NONE = 0,
|
||||||
"couleur" */
|
PS_TOTALLY_OUT = 1,
|
||||||
SO_USE_TEXTURE = 1, /* utiliser la texture pour
|
PS_PARTIALLY_OUT = 2,
|
||||||
colorer (multiplication si
|
PS_CULL = 4, /* si en BACKFACE et que
|
||||||
SO_USE_COLOR est actif) */
|
SO_CULL_BACKFACES est actif */
|
||||||
SO_USE_COLOR = 2, /* utiliser la couleur de la
|
PS_TOO_FAR = 8,
|
||||||
surface ou des sommets pour
|
PS_OUT_LEFT = 16,
|
||||||
colorer (multiplication si
|
PS_OUT_RIGHT = 32,
|
||||||
SO_USE_TEXTURE est actif) */
|
PS_OUT_BOTTOM = 64,
|
||||||
SO_COLOR_MATERIAL = 4, /* utiliser la couleur aux
|
PS_OUT_TOP = 128,
|
||||||
sommets si actif
|
PS_OUT_NEAR = 256,
|
||||||
(nécessite aussi
|
PS_OUT_FAR = 512
|
||||||
l'activation de
|
};
|
||||||
SO_USE_COLOR) */
|
|
||||||
SO_CULL_BACKFACES = 8, /* active le fait de cacher
|
|
||||||
les faces arrières */
|
|
||||||
SO_USE_LIGHTING = 16, /* active le calcul d'ombre
|
|
||||||
propre (Gouraud sur
|
|
||||||
diffus) */
|
|
||||||
SO_DEFAULT = SO_CULL_BACKFACES | SO_USE_COLOR /* comportement
|
|
||||||
par
|
|
||||||
défaut */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct vec4 {
|
/*!\brief options pour les surfaces */
|
||||||
|
enum soptions_t {
|
||||||
|
SO_NONE = 0, /* la surface n'a pas de rendu
|
||||||
|
"couleur" */
|
||||||
|
SO_USE_TEXTURE = 1, /* utiliser la texture pour
|
||||||
|
colorer (multiplication si
|
||||||
|
SO_USE_COLOR est actif) */
|
||||||
|
SO_USE_COLOR = 2, /* utiliser la couleur de la
|
||||||
|
surface ou des sommets pour
|
||||||
|
colorer (multiplication si
|
||||||
|
SO_USE_TEXTURE est actif) */
|
||||||
|
SO_COLOR_MATERIAL = 4, /* utiliser la couleur aux
|
||||||
|
sommets si actif
|
||||||
|
(nécessite aussi
|
||||||
|
l'activation de
|
||||||
|
SO_USE_COLOR) */
|
||||||
|
SO_CULL_BACKFACES = 8, /* active le fait de cacher
|
||||||
|
les faces arrières */
|
||||||
|
SO_USE_LIGHTING = 16, /* active le calcul d'ombre
|
||||||
|
propre (Gouraud sur
|
||||||
|
diffus) */
|
||||||
|
SO_DEFAULT = SO_CULL_BACKFACES | SO_USE_COLOR /* comportement
|
||||||
|
par
|
||||||
|
défaut */
|
||||||
|
};
|
||||||
|
|
||||||
|
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 */
|
|
||||||
extern void transform_n_rasterize(surface_t * s, float * model_view_matrix, float * projection_matrix);
|
|
||||||
extern void clear_depth_map(void);
|
|
||||||
extern void set_texture(GLuint screen);
|
|
||||||
extern void updatesfuncs(surface_t * s);
|
|
||||||
|
|
||||||
/* dans vtranform.c */
|
/* dans rasterize.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 void transform_n_rasterize(surface_t * s, float * model_view_matrix, float * projection_matrix);
|
||||||
extern void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport);
|
extern void clear_depth_map(void);
|
||||||
extern void mult_matrix(float * res, float * m);
|
extern void set_texture(GLuint screen);
|
||||||
extern void translate(float * m, float tx, float ty, float tz);
|
extern void updatesfuncs(surface_t * s);
|
||||||
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 lookAt(float * m, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
|
|
||||||
|
|
||||||
/* dans surface.c */
|
|
||||||
extern void tnormal(triangle_t * t);
|
|
||||||
extern void snormals(surface_t * s);
|
|
||||||
extern void tnormals2vertices(surface_t * s);
|
|
||||||
extern void set_texture_id(surface_t * s, GLuint tex_id);
|
|
||||||
extern void set_diffuse_color(surface_t * s, vec4 dcolor);
|
|
||||||
extern void enable_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 void free_surface(surface_t * s);
|
|
||||||
extern GLuint get_texture_from_BMP(const char * filename);
|
|
||||||
|
|
||||||
/* dans geometry.c */
|
/* dans vtranform.c */
|
||||||
extern surface_t * mk_quad(void);
|
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 surface_t * mk_cube(void);
|
extern void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport);
|
||||||
extern surface_t * mk_sphere(int longitudes, int latitudes);
|
extern void mult_matrix(float * res, float * m);
|
||||||
|
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 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);
|
||||||
|
|
||||||
|
/* dans surface.c */
|
||||||
|
extern void tnormal(triangle_t * t);
|
||||||
|
extern void snormals(surface_t * s);
|
||||||
|
extern void tnormals2vertices(surface_t * s);
|
||||||
|
extern void set_texture_id(surface_t * s, GLuint tex_id);
|
||||||
|
extern void set_diffuse_color(surface_t * s, vec4 dcolor);
|
||||||
|
extern void enable_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 void free_surface(surface_t * s);
|
||||||
|
extern GLuint get_texture_from_BMP(const char * filename);
|
||||||
|
|
||||||
|
/* dans geometry.c */
|
||||||
|
extern surface_t * mk_quad(void);
|
||||||
|
extern surface_t * mk_cube(void);
|
||||||
|
extern surface_t * mk_sphere(int longitudes, int latitudes);
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
122
surface.c
122
surface.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
322
vtransform.c
322
vtransform.c
|
@ -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
|
||||||
|
@ -82,132 +82,132 @@ vertex_t vtransform(surface_t * s, vertex_t v, float * model_view_matrix, float
|
||||||
* surface. Elle utilise aussi \a clip2_unit_cube pour connaître l'état
|
* surface. Elle utilise aussi \a clip2_unit_cube pour connaître l'état
|
||||||
* du triangle par rapport au cube unitaire.
|
* du triangle par rapport au cube unitaire.
|
||||||
*
|
*
|
||||||
* \see vtransform
|
* \see vtransform
|
||||||
* \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
|
||||||
|
|
302
window.c
302
window.c
|
@ -1,4 +1,4 @@
|
||||||
/*!\file window.c
|
/*!\file window.c
|
||||||
* \brief Utilisation du raster DIY comme pipeline de rendu 3D. Cet
|
* \brief Utilisation du raster DIY comme pipeline de rendu 3D. Cet
|
||||||
* exemple montre les géométries disponibles et quelques
|
* exemple montre les géométries disponibles et quelques
|
||||||
* transformations dessus.
|
* transformations dessus.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue