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
|
||||
* (quad), un cube et une sphere.
|
||||
*
|
||||
* \author Farès BELHADJ, amsi@up8.edu
|
||||
* \date November, 2021.
|
||||
* \date November, 2021.
|
||||
*/
|
||||
#include "rasterize.h"
|
||||
#include <assert.h>
|
||||
|
@ -17,141 +17,141 @@
|
|||
* quadrilatère "debout" et à la profondeur 0. Il fait la hauteur et
|
||||
* la largeur du cube unitaire (-1 à 1).*/
|
||||
surface_t * mk_quad(void) {
|
||||
static const float
|
||||
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, 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, 1.0f, -1.0f
|
||||
};
|
||||
static const int order[] = { 0, 1, 2, 2, 1, 3 };
|
||||
surface_t * s;
|
||||
/* on met du jaune partout */
|
||||
const vec4 color0 = { 1.0f, 1.0f, 0.0f, 1.0f };
|
||||
triangle_t t[2];
|
||||
int i, j, k, o;
|
||||
for(i = 0, o = 0; i < 2; ++i)
|
||||
for(j = 0; j < 3; ++j, ++o) {
|
||||
k = order[o] * 8;
|
||||
t[i].v[j].position = *(vec4 *)&(data[k]);
|
||||
t[i].v[j].position.w = 1.0f;
|
||||
t[i].v[j].normal = *(vec3 *)&(data[k + 3]);
|
||||
t[i].v[j].texCoord = *(vec2 *)&(data[k + 6]);
|
||||
t[i].v[j].color0 = color0;
|
||||
}
|
||||
s = new_surface(t, 2, 1, 1);
|
||||
snormals(s);
|
||||
return s;
|
||||
static const float
|
||||
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, 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, 1.0f, -1.0f
|
||||
};
|
||||
static const int order[] = { 0, 1, 2, 2, 1, 3 };
|
||||
surface_t * s;
|
||||
/* on met du jaune partout */
|
||||
const vec4 color0 = { 1.0f, 1.0f, 0.0f, 1.0f };
|
||||
triangle_t t[2];
|
||||
int i, j, k, o;
|
||||
for(i = 0, o = 0; i < 2; ++i)
|
||||
for(j = 0; j < 3; ++j, ++o) {
|
||||
k = order[o] * 8;
|
||||
t[i].v[j].position = *(vec4 *)&(data[k]);
|
||||
t[i].v[j].position.w = 1.0f;
|
||||
t[i].v[j].normal = *(vec3 *)&(data[k + 3]);
|
||||
t[i].v[j].texCoord = *(vec2 *)&(data[k + 6]);
|
||||
t[i].v[j].color0 = color0;
|
||||
}
|
||||
s = new_surface(t, 2, 1, 1);
|
||||
snormals(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*!\brief fabrique et renvoie une surface représentant un
|
||||
* cube unitaire (de -1 à 1).*/
|
||||
surface_t * mk_cube(void) {
|
||||
const float
|
||||
data[] = {
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f
|
||||
};
|
||||
const int order[] = { 0, 1, 2, 2, 1, 3 };
|
||||
surface_t * s;
|
||||
/* on met du vert-clair partout */
|
||||
const vec4 color0 = { 0.5f, 1.0f, 0.0f, 1.0f };
|
||||
triangle_t t[12];
|
||||
int i, j, k, o;
|
||||
for(i = 0, o = 0; i < 12; ++i)
|
||||
for(j = 0; j < 3; ++j, ++o) {
|
||||
k = 8 * (order[o % 6] + 4 * (i / 2));
|
||||
t[i].v[j].position = *(vec4 *)&(data[k]);
|
||||
t[i].v[j].position.w = 1.0f;
|
||||
t[i].v[j].normal = *(vec3 *)&(data[k + 3]);
|
||||
t[i].v[j].texCoord = *(vec2 *)&(data[k + 6]);
|
||||
t[i].v[j].color0 = color0;
|
||||
}
|
||||
s = new_surface(t, 12, 1, 1);
|
||||
snormals(s);
|
||||
return s;
|
||||
const float
|
||||
data[] = {
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f,
|
||||
/* 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, 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, 1.0f, 1.0f
|
||||
};
|
||||
const int order[] = { 0, 1, 2, 2, 1, 3 };
|
||||
surface_t * s;
|
||||
/* on met du vert-clair partout */
|
||||
const vec4 color0 = { 0.5f, 1.0f, 0.0f, 1.0f };
|
||||
triangle_t t[12];
|
||||
int i, j, k, o;
|
||||
for(i = 0, o = 0; i < 12; ++i)
|
||||
for(j = 0; j < 3; ++j, ++o) {
|
||||
k = 8 * (order[o % 6] + 4 * (i / 2));
|
||||
t[i].v[j].position = *(vec4 *)&(data[k]);
|
||||
t[i].v[j].position.w = 1.0f;
|
||||
t[i].v[j].normal = *(vec3 *)&(data[k + 3]);
|
||||
t[i].v[j].texCoord = *(vec2 *)&(data[k + 6]);
|
||||
t[i].v[j].color0 = color0;
|
||||
}
|
||||
s = new_surface(t, 12, 1, 1);
|
||||
snormals(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*!\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
|
||||
* longitudes et \a latitudes latitudes. */
|
||||
surface_t * mk_sphere(int longitudes, int latitudes) {
|
||||
triangle_t * t;
|
||||
vertex_t * data;
|
||||
double phi, theta, r, y;
|
||||
double c2MPI_Long = 2.0 * M_PI / longitudes;
|
||||
double cMPI_Lat = M_PI / latitudes;
|
||||
/* on met du vert-clair partout */
|
||||
const vec4 color0 = { 0.5f, 1.0f, 0.0f, 1.0f };
|
||||
int z, nz, x, nx, zw, nzw, k, n = 2 * longitudes * latitudes;
|
||||
assert(n);
|
||||
data = malloc((longitudes + 1) * (latitudes + 1) * sizeof *data);
|
||||
assert(data);
|
||||
t = malloc(n * sizeof *t);
|
||||
assert(t);
|
||||
for(z = 0, k = 0; z <= latitudes; ++z) {
|
||||
theta = -M_PI_2 + z * cMPI_Lat;
|
||||
y = sin(theta);
|
||||
r = cos(theta);
|
||||
for(x = 0; x <= longitudes; ++x, ++k) {
|
||||
phi = x * c2MPI_Long;
|
||||
data[k].position.x = r * cos(phi);
|
||||
data[k].position.y = y;
|
||||
data[k].position.z = r * sin(phi);
|
||||
data[k].position.w = 1.0f;
|
||||
data[k].texCoord.x = phi / (2.0 * M_PI);
|
||||
data[k].texCoord.y = (theta + M_PI_2) / M_PI;
|
||||
data[k].color0 = color0;
|
||||
/* gcc 7.5 et plus abusent : data[k].normal = *(vec3 *)&(data[k].position); */
|
||||
data[k].normal.x = data[k].position.x;
|
||||
data[k].normal.y = data[k].position.y;
|
||||
data[k].normal.z = data[k].position.z;
|
||||
triangle_t * t;
|
||||
vertex_t * data;
|
||||
double phi, theta, r, y;
|
||||
double c2MPI_Long = 2.0 * M_PI / longitudes;
|
||||
double cMPI_Lat = M_PI / latitudes;
|
||||
/* on met du vert-clair partout */
|
||||
const vec4 color0 = { 0.5f, 1.0f, 0.0f, 1.0f };
|
||||
int z, nz, x, nx, zw, nzw, k, n = 2 * longitudes * latitudes;
|
||||
assert(n);
|
||||
data = malloc((longitudes + 1) * (latitudes + 1) * sizeof *data);
|
||||
assert(data);
|
||||
t = malloc(n * sizeof *t);
|
||||
assert(t);
|
||||
for(z = 0, k = 0; z <= latitudes; ++z) {
|
||||
theta = -M_PI_2 + z * cMPI_Lat;
|
||||
y = sin(theta);
|
||||
r = cos(theta);
|
||||
for(x = 0; x <= longitudes; ++x, ++k) {
|
||||
phi = x * c2MPI_Long;
|
||||
data[k].position.x = r * cos(phi);
|
||||
data[k].position.y = y;
|
||||
data[k].position.z = r * sin(phi);
|
||||
data[k].position.w = 1.0f;
|
||||
data[k].texCoord.x = phi / (2.0 * M_PI);
|
||||
data[k].texCoord.y = (theta + M_PI_2) / M_PI;
|
||||
data[k].color0 = color0;
|
||||
/* gcc 7.5 et plus abusent : data[k].normal = *(vec3 *)&(data[k].position); */
|
||||
data[k].normal.x = data[k].position.x;
|
||||
data[k].normal.y = data[k].position.y;
|
||||
data[k].normal.z = data[k].position.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(z = 0, k = 0; z < latitudes; ++z) {
|
||||
nz = z + 1;
|
||||
zw = z * (longitudes + 1);
|
||||
nzw = nz * (longitudes + 1);
|
||||
for(x = 0; x < longitudes; ++x) {
|
||||
nx = x + 1;
|
||||
t[k].v[0] = data[zw + x];
|
||||
t[k].v[1] = data[nzw + x];
|
||||
t[k].v[2] = data[zw + nx];
|
||||
tnormal(&t[k]);++k;
|
||||
t[k].v[0] = data[zw + nx];
|
||||
t[k].v[1] = data[nzw + x];
|
||||
t[k].v[2] = data[nzw + nx];
|
||||
tnormal(&t[k]);++k;
|
||||
for(z = 0, k = 0; z < latitudes; ++z) {
|
||||
nz = z + 1;
|
||||
zw = z * (longitudes + 1);
|
||||
nzw = nz * (longitudes + 1);
|
||||
for(x = 0; x < longitudes; ++x) {
|
||||
nx = x + 1;
|
||||
t[k].v[0] = data[zw + x];
|
||||
t[k].v[1] = data[nzw + x];
|
||||
t[k].v[2] = data[zw + nx];
|
||||
tnormal(&t[k]);++k;
|
||||
t[k].v[0] = data[zw + nx];
|
||||
t[k].v[1] = data[nzw + x];
|
||||
t[k].v[2] = data[nzw + nx];
|
||||
tnormal(&t[k]);++k;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
return new_surface(t, n, 0, 1);
|
||||
free(data);
|
||||
return new_surface(t, n, 0, 1);
|
||||
}
|
||||
|
|
581
rasterize.c
581
rasterize.c
|
@ -3,7 +3,7 @@
|
|||
* principalement que du cas du triangle.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \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 blue(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 */
|
||||
static GLuint * _tex = NULL;
|
||||
|
@ -53,71 +53,72 @@ static int _perpective_correction = 0;
|
|||
/*!\brief transforme et rastérise l'ensemble des triangles de la
|
||||
* surface. */
|
||||
void transform_n_rasterize(surface_t * s, float * model_view_matrix, float * projection_matrix) {
|
||||
int i;
|
||||
/* la première fois allouer le depth buffer */
|
||||
if(_depth == NULL) {
|
||||
_depth = calloc(gl4dpGetWidth() * gl4dpGetHeight(), sizeof *_depth);
|
||||
assert(_depth);
|
||||
atexit(pquit);
|
||||
}
|
||||
/* si projection_matrix[15] est à 1, c'est une projection orthogonale, pas
|
||||
* besoin de correction de perspective */
|
||||
_perpective_correction = projection_matrix[15] == 1.0f ? 0 : 1;
|
||||
/* le viewport est fixe ; \todo peut devenir paramétrable ... */
|
||||
float viewport[] = { 0.0f, 0.0f, (float)gl4dpGetWidth(), (float)gl4dpGetHeight() };
|
||||
stransform(s, model_view_matrix, projection_matrix, viewport);
|
||||
/* mettre en place la texture qui sera utilisée pour mapper la surface */
|
||||
if(s->options & SO_USE_TEXTURE)
|
||||
set_texture(s->tex_id);
|
||||
for(i = 0; i < s->n; ++i) {
|
||||
/* si le triangle est déclaré CULL (par exemple en backface), le rejeter */
|
||||
if(s->t[i].state & PS_CULL ) continue;
|
||||
/* on rejette aussi les triangles complètement out */
|
||||
if(s->t[i].state & PS_TOTALLY_OUT) continue;
|
||||
/* "hack" pas terrible permettant de rejeter les triangles
|
||||
* partiellement out dont au moins un sommet est TOO_FAR (trop
|
||||
* éloigné). Voir le fichier transformations.c pour voir comment
|
||||
* améliorer ce traitement. */
|
||||
if( s->t[i].state & PS_PARTIALLY_OUT &&
|
||||
( (s->t[i].v[0].state & PS_TOO_FAR) ||
|
||||
(s->t[i].v[1].state & PS_TOO_FAR) ||
|
||||
(s->t[i].v[2].state & PS_TOO_FAR) ) )
|
||||
continue;
|
||||
fill_triangle(s, &(s->t[i]));
|
||||
}
|
||||
int i;
|
||||
/* la première fois allouer le depth buffer */
|
||||
if(_depth == NULL) {
|
||||
_depth = calloc(gl4dpGetWidth() * gl4dpGetHeight(), sizeof *_depth);
|
||||
assert(_depth);
|
||||
atexit(pquit);
|
||||
}
|
||||
/* si projection_matrix[15] est à 1, c'est une projection orthogonale, pas
|
||||
* besoin de correction de perspective */
|
||||
_perpective_correction = projection_matrix[15] == 1.0f ? 0 : 1;
|
||||
/* le viewport est fixe ; \todo peut devenir paramétrable ... */
|
||||
float viewport[] = { 0.0f, 0.0f, (float)gl4dpGetWidth(), (float)gl4dpGetHeight() };
|
||||
stransform(s, model_view_matrix, projection_matrix, viewport);
|
||||
/* mettre en place la texture qui sera utilisée pour mapper la surface */
|
||||
if(s->options & SO_USE_TEXTURE)
|
||||
set_texture(s->tex_id);
|
||||
for(i = 0; i < s->n; ++i) {
|
||||
/* si le triangle est déclaré CULL (par exemple en backface), le rejeter */
|
||||
if(s->t[i].state & PS_CULL ) continue;
|
||||
/* on rejette aussi les triangles complètement out */
|
||||
if(s->t[i].state & PS_TOTALLY_OUT) continue;
|
||||
/* "hack" pas terrible permettant de rejeter les triangles
|
||||
* partiellement out dont au moins un sommet est TOO_FAR (trop
|
||||
* éloigné). Voir le fichier transformations.c pour voir comment
|
||||
* améliorer ce traitement. */
|
||||
if( s->t[i].state & PS_PARTIALLY_OUT &&
|
||||
( (s->t[i].v[0].state & PS_TOO_FAR) ||
|
||||
(s->t[i].v[1].state & PS_TOO_FAR) ||
|
||||
(s->t[i].v[2].state & PS_TOO_FAR) )
|
||||
)
|
||||
continue;
|
||||
fill_triangle(s, &(s->t[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/*!\brief effacer le buffer de profondeur (à chaque frame) pour
|
||||
* réaliser le z-test */
|
||||
void clear_depth_map(void) {
|
||||
if(_depth) {
|
||||
memset(_depth, 0, gl4dpGetWidth() * gl4dpGetHeight() * sizeof *_depth);
|
||||
}
|
||||
if(_depth) {
|
||||
memset(_depth, 0, gl4dpGetWidth() * gl4dpGetHeight() * sizeof *_depth);
|
||||
}
|
||||
}
|
||||
|
||||
/*!\brief met en place une texture pour être mappée sur la surface en cours */
|
||||
void set_texture(GLuint screen) {
|
||||
GLuint old_id = gl4dpGetTextureId(); /* au cas où */
|
||||
gl4dpSetScreen(screen);
|
||||
_tex = gl4dpGetPixels();
|
||||
_texW = gl4dpGetWidth();
|
||||
_texH = gl4dpGetHeight();
|
||||
if(old_id)
|
||||
gl4dpSetScreen(old_id);
|
||||
GLuint old_id = gl4dpGetTextureId(); /* au cas où */
|
||||
gl4dpSetScreen(screen);
|
||||
_tex = gl4dpGetPixels();
|
||||
_texW = gl4dpGetWidth();
|
||||
_texH = gl4dpGetHeight();
|
||||
if(old_id)
|
||||
gl4dpSetScreen(old_id);
|
||||
}
|
||||
|
||||
|
||||
/*!\brief met à jour la fonction d'interpolation et de coloriage
|
||||
* (shadingfunc) de la surface en fonction de ses options */
|
||||
void updatesfuncs(surface_t * s) {
|
||||
int t;
|
||||
if(s->options & SO_USE_TEXTURE) {
|
||||
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;
|
||||
} else {
|
||||
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;;
|
||||
}
|
||||
int t;
|
||||
if(s->options & SO_USE_TEXTURE) {
|
||||
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;
|
||||
} else {
|
||||
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;;
|
||||
}
|
||||
}
|
||||
|
||||
/*!\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).
|
||||
*/
|
||||
inline void fill_triangle(surface_t * s, triangle_t * t) {
|
||||
vertex_t * aG = NULL, * aD = NULL;
|
||||
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[2].y) {
|
||||
bas = 0;
|
||||
if(t->v[1].y < t->v[2].y) {
|
||||
median = 1;
|
||||
haut = 2;
|
||||
} else {
|
||||
median = 2;
|
||||
haut = 1;
|
||||
}
|
||||
} else {
|
||||
bas = 2;
|
||||
median = 0;
|
||||
haut = 1;
|
||||
vertex_t * aG = NULL, * aD = NULL;
|
||||
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[2].y) {
|
||||
bas = 0;
|
||||
if(t->v[1].y < t->v[2].y) {
|
||||
median = 1;
|
||||
haut = 2;
|
||||
} else {
|
||||
median = 2;
|
||||
haut = 1;
|
||||
}
|
||||
} else {
|
||||
bas = 2;
|
||||
median = 0;
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
n = t->v[haut].y - t->v[bas].y + 1;
|
||||
aG = malloc(n * sizeof *aG);
|
||||
assert(aG);
|
||||
aD = malloc(n * sizeof *aD);
|
||||
assert(aD);
|
||||
/* est-ce que Pm est à gauche (+) ou à droite (-) de la droite (Pb->Ph) ? */
|
||||
/* idée TODO?, un produit vectoriel pourrait s'avérer mieux */
|
||||
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; */
|
||||
signe = (t->v[median].x > t->v[haut].x) ? -1 : 1;
|
||||
} else {
|
||||
bas = 2;
|
||||
median = 1;
|
||||
haut = 0;
|
||||
/* eq ax + y + c = 0 */
|
||||
float a, c, x;
|
||||
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;
|
||||
}
|
||||
}
|
||||
n = t->v[haut].y - t->v[bas].y + 1;
|
||||
aG = malloc(n * sizeof *aG);
|
||||
assert(aG);
|
||||
aD = malloc(n * sizeof *aD);
|
||||
assert(aD);
|
||||
/* est-ce que Pm est à gauche (+) ou à droite (-) de la droite (Pb->Ph) ? */
|
||||
/* idée TODO?, un produit vectoriel pourrait s'avérer mieux */
|
||||
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; */
|
||||
signe = (t->v[median].x > t->v[haut].x) ? -1 : 1;
|
||||
} else {
|
||||
/* eq ax + y + c = 0 */
|
||||
float a, c, x;
|
||||
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 */
|
||||
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);
|
||||
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
|
||||
* triangle à remplir (par \a horizontal_line).
|
||||
*/
|
||||
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;
|
||||
float dmax = sqrtf(u * u + v * v), p;
|
||||
u = abs(u); v = abs(v);
|
||||
if(u > v) { // 1er octan
|
||||
if(replace) {
|
||||
int objX = (u + 1) * pasX;
|
||||
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) {
|
||||
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);
|
||||
if(delta < 0) {
|
||||
++k;
|
||||
y += pasY;
|
||||
delta += incO;
|
||||
} else
|
||||
delta += incH;
|
||||
}
|
||||
} else {
|
||||
int objX = (u + 1) * pasX;
|
||||
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) {
|
||||
if(!done) {
|
||||
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);
|
||||
done = 1;
|
||||
}
|
||||
if(delta < 0) {
|
||||
++k;
|
||||
done = 0;
|
||||
y += pasY;
|
||||
delta += incO;
|
||||
} else
|
||||
delta += incH;
|
||||
}
|
||||
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;
|
||||
u = abs(u); v = abs(v);
|
||||
if(u > v) { // 1er octan
|
||||
if(replace) {
|
||||
int objX = (u + 1) * pasX;
|
||||
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) {
|
||||
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);
|
||||
if(delta < 0) {
|
||||
++k;
|
||||
y += pasY;
|
||||
delta += incO;
|
||||
} else
|
||||
delta += incH;
|
||||
}
|
||||
} else {
|
||||
int objX = (u + 1) * pasX;
|
||||
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) {
|
||||
if(!done) {
|
||||
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);
|
||||
done = 1;
|
||||
}
|
||||
if(delta < 0) {
|
||||
++k;
|
||||
done = 0;
|
||||
y += pasY;
|
||||
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;
|
||||
}
|
||||
}
|
||||
} 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 */
|
||||
inline void horizontal_line(surface_t * s, vertex_t * vG, vertex_t * vD) {
|
||||
int w = gl4dpGetWidth(), x, yw = vG->y * w;
|
||||
GLuint * image = gl4dpGetPixels();
|
||||
float dmax = vD->x - vG->x, p, deltap;
|
||||
vertex_t v;
|
||||
/* il reste d'autres optims possibles */
|
||||
for(x = vG->x, p = 0.0f, deltap = 1.0f / dmax; x <= vD->x; ++x, p += deltap)
|
||||
if(x >= 0 && x < w) {
|
||||
s->interpolatefunc(&v, vG, vD, 1.0f - p, p);
|
||||
if(v.z < 0 || v.z > 1 || v.z < _depth[yw + x]) { continue; }
|
||||
s->shadingfunc(s, &image[yw + x], &v);
|
||||
_depth[yw + x] = v.z;
|
||||
}
|
||||
int w = gl4dpGetWidth(), x, yw = vG->y * w;
|
||||
GLuint * image = gl4dpGetPixels();
|
||||
float dmax = vD->x - vG->x, p, deltap;
|
||||
vertex_t v;
|
||||
/* il reste d'autres optims possibles */
|
||||
for(x = vG->x, p = 0.0f, deltap = 1.0f / dmax; x <= vD->x; ++x, p += deltap)
|
||||
if(x >= 0 && x < w) {
|
||||
s->interpolatefunc(&v, vG, vD, 1.0f - p, p);
|
||||
if(v.z < 0 || v.z > 1 || v.z < _depth[yw + x]) { continue; }
|
||||
s->shadingfunc(s, &image[yw + x], &v);
|
||||
_depth[yw + x] = v.z;
|
||||
}
|
||||
}
|
||||
/*!\brief aucune couleur n'est inscrite */
|
||||
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 */
|
||||
inline void shading_only_tex(surface_t * s, GLuint * pcolor, vertex_t * v) {
|
||||
int xt, yt, ct;
|
||||
GLubyte r, g, b, a;
|
||||
xt = (int)(v->texCoord.x * (_texW - EPSILON));
|
||||
if(xt < 0) {
|
||||
xt = xt % (-_texW);
|
||||
while(xt < 0) xt += _texW;
|
||||
} else
|
||||
xt = xt % _texW;
|
||||
yt = (int)(v->texCoord.y * (_texH - EPSILON));
|
||||
if(yt < 0) {
|
||||
yt = yt % (-_texH);
|
||||
while(yt < 0) yt += _texH;
|
||||
} else
|
||||
yt = yt % _texH;
|
||||
ct = yt * _texW + xt;
|
||||
*pcolor = _tex[yt * _texW + xt];
|
||||
r = (GLubyte)( red(_tex[ct]) * v->li);
|
||||
g = (GLubyte)(green(_tex[ct]) * v->li);
|
||||
b = (GLubyte)( blue(_tex[ct]) * v->li);
|
||||
a = (GLubyte) alpha(_tex[ct]);
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
int xt, yt, ct;
|
||||
GLubyte r, g, b, a;
|
||||
xt = (int)(v->texCoord.x * (_texW - EPSILON));
|
||||
if(xt < 0) {
|
||||
xt = xt % (-_texW);
|
||||
while(xt < 0) xt += _texW;
|
||||
} else
|
||||
xt = xt % _texW;
|
||||
yt = (int)(v->texCoord.y * (_texH - EPSILON));
|
||||
if(yt < 0) {
|
||||
yt = yt % (-_texH);
|
||||
while(yt < 0) yt += _texH;
|
||||
} else
|
||||
yt = yt % _texH;
|
||||
ct = yt * _texW + xt;
|
||||
*pcolor = _tex[yt * _texW + xt];
|
||||
r = (GLubyte)( red(_tex[ct]) * v->li);
|
||||
g = (GLubyte)(green(_tex[ct]) * v->li);
|
||||
b = (GLubyte)( blue(_tex[ct]) * v->li);
|
||||
a = (GLubyte) alpha(_tex[ct]);
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
/*!\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) {
|
||||
GLubyte r, g, b, a;
|
||||
r = (GLubyte)(v->li * v->icolor.x * (255 + EPSILON));
|
||||
g = (GLubyte)(v->li * v->icolor.y * (255 + EPSILON));
|
||||
b = (GLubyte)(v->li * v->icolor.z * (255 + EPSILON));
|
||||
a = (GLubyte)(v->icolor.w * (255 + EPSILON));
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
GLubyte r, g, b, a;
|
||||
r = (GLubyte)(v->li * v->icolor.x * (255 + EPSILON));
|
||||
g = (GLubyte)(v->li * v->icolor.y * (255 + EPSILON));
|
||||
b = (GLubyte)(v->li * v->icolor.z * (255 + EPSILON));
|
||||
a = (GLubyte)(v->icolor.w * (255 + EPSILON));
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
/*!\brief la couleur du pixel est tirée de la couleur diffuse de la
|
||||
* surface */
|
||||
inline void shading_only_color(surface_t * s, GLuint * pcolor, vertex_t * v) {
|
||||
GLubyte r, g, b, a;
|
||||
r = (GLubyte)(v->li * s->dcolor.x * (255 + EPSILON));
|
||||
g = (GLubyte)(v->li * s->dcolor.y * (255 + EPSILON));
|
||||
b = (GLubyte)(v->li * s->dcolor.z * (255 + EPSILON));
|
||||
a = (GLubyte)(s->dcolor.w * (255 + EPSILON));
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
GLubyte r, g, b, a;
|
||||
r = (GLubyte)(v->li * s->dcolor.x * (255 + EPSILON));
|
||||
g = (GLubyte)(v->li * s->dcolor.y * (255 + EPSILON));
|
||||
b = (GLubyte)(v->li * s->dcolor.z * (255 + EPSILON));
|
||||
a = (GLubyte)(s->dcolor.w * (255 + EPSILON));
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
/*!\brief la couleur du pixel est le produit de la couleur interpolée
|
||||
* et de la texture */
|
||||
inline void shading_all_CM(surface_t * s, GLuint * pcolor, vertex_t * v) {
|
||||
GLubyte r, g, b, a;
|
||||
int xt, yt, ct;
|
||||
xt = (int)(v->texCoord.x * (_texW - EPSILON));
|
||||
if(xt < 0) {
|
||||
xt = xt % (-_texW);
|
||||
while(xt < 0) xt += _texW;
|
||||
} else
|
||||
xt = xt % _texW;
|
||||
yt = (int)(v->texCoord.y * (_texH - EPSILON));
|
||||
if(yt < 0) {
|
||||
yt = yt % (-_texH);
|
||||
while(yt < 0) yt += _texH;
|
||||
} else
|
||||
yt = yt % _texH;
|
||||
ct = yt * _texW + xt;
|
||||
r = (GLubyte)(( red(_tex[ct]) + EPSILON) * v->li * v->icolor.x);
|
||||
g = (GLubyte)((green(_tex[ct]) + EPSILON) * v->li * v->icolor.y);
|
||||
b = (GLubyte)(( blue(_tex[ct]) + EPSILON) * v->li * v->icolor.z);
|
||||
a = (GLubyte)((alpha(_tex[ct]) + EPSILON) * v->icolor.w);
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
GLubyte r, g, b, a;
|
||||
int xt, yt, ct;
|
||||
xt = (int)(v->texCoord.x * (_texW - EPSILON));
|
||||
if(xt < 0) {
|
||||
xt = xt % (-_texW);
|
||||
while(xt < 0) xt += _texW;
|
||||
} else
|
||||
xt = xt % _texW;
|
||||
yt = (int)(v->texCoord.y * (_texH - EPSILON));
|
||||
if(yt < 0) {
|
||||
yt = yt % (-_texH);
|
||||
while(yt < 0) yt += _texH;
|
||||
} else
|
||||
yt = yt % _texH;
|
||||
ct = yt * _texW + xt;
|
||||
r = (GLubyte)(( red(_tex[ct]) + EPSILON) * v->li * v->icolor.x);
|
||||
g = (GLubyte)((green(_tex[ct]) + EPSILON) * v->li * v->icolor.y);
|
||||
b = (GLubyte)(( blue(_tex[ct]) + EPSILON) * v->li * v->icolor.z);
|
||||
a = (GLubyte)((alpha(_tex[ct]) + EPSILON) * v->icolor.w);
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
/*!\brief la couleur du pixel est le produit de la couleur diffuse
|
||||
* de la surface et de la texture */
|
||||
inline void shading_all(surface_t * s, GLuint * pcolor, vertex_t * v) {
|
||||
GLubyte r, g, b, a;
|
||||
int xt, yt, ct;
|
||||
xt = (int)(v->texCoord.x * (_texW - EPSILON));
|
||||
if(xt < 0) {
|
||||
xt = xt % (-_texW);
|
||||
while(xt < 0) xt += _texW;
|
||||
} else
|
||||
xt = xt % _texW;
|
||||
yt = (int)(v->texCoord.y * (_texH - EPSILON));
|
||||
if(yt < 0) {
|
||||
yt = yt % (-_texH);
|
||||
while(yt < 0) yt += _texH;
|
||||
} else
|
||||
yt = yt % _texH;
|
||||
ct = yt * _texW + xt;
|
||||
r = (GLubyte)(( red(_tex[ct]) + EPSILON) * v->li * s->dcolor.x);
|
||||
g = (GLubyte)((green(_tex[ct]) + EPSILON) * v->li * s->dcolor.y);
|
||||
b = (GLubyte)(( blue(_tex[ct]) + EPSILON) * v->li * s->dcolor.z);
|
||||
a = (GLubyte)((alpha(_tex[ct]) + EPSILON) * s->dcolor.w);
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
GLubyte r, g, b, a;
|
||||
int xt, yt, ct;
|
||||
xt = (int)(v->texCoord.x * (_texW - EPSILON));
|
||||
if(xt < 0) {
|
||||
xt = xt % (-_texW);
|
||||
while(xt < 0) xt += _texW;
|
||||
} else
|
||||
xt = xt % _texW;
|
||||
yt = (int)(v->texCoord.y * (_texH - EPSILON));
|
||||
if(yt < 0) {
|
||||
yt = yt % (-_texH);
|
||||
while(yt < 0) yt += _texH;
|
||||
} else
|
||||
yt = yt % _texH;
|
||||
ct = yt * _texW + xt;
|
||||
r = (GLubyte)(( red(_tex[ct]) + EPSILON) * v->li * s->dcolor.x);
|
||||
g = (GLubyte)((green(_tex[ct]) + EPSILON) * v->li * s->dcolor.y);
|
||||
b = (GLubyte)(( blue(_tex[ct]) + EPSILON) * v->li * s->dcolor.z);
|
||||
a = (GLubyte)((alpha(_tex[ct]) + EPSILON) * s->dcolor.w);
|
||||
*pcolor = rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
/*!\brief interpolation de plusieurs floattants (entre \a s et \a e)
|
||||
* 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
|
||||
* un _perpective_correction != 0 ??? */
|
||||
inline void interpolate(vertex_t * r, vertex_t * a, vertex_t * b, float fa, float fb, int s, int e) {
|
||||
int i;
|
||||
float * pr = (float *)&(r->texCoord);
|
||||
float * pa = (float *)&(a->texCoord);
|
||||
float * pb = (float *)&(b->texCoord);
|
||||
/* Correction de l'interpolation par rapport à la perspective, le z
|
||||
* joue un rôle dans les distances, il est nécessaire de le
|
||||
* 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
|
||||
*/
|
||||
if(_perpective_correction) {
|
||||
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 */
|
||||
pr[e] = fa * pa[e] + fb * pb[e];
|
||||
e = 7;
|
||||
int i;
|
||||
float * pr = (float *)&(r->texCoord);
|
||||
float * pa = (float *)&(a->texCoord);
|
||||
float * pb = (float *)&(b->texCoord);
|
||||
/* Correction de l'interpolation par rapport à la perspective, le z
|
||||
* joue un rôle dans les distances, il est nécessaire de le
|
||||
* 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
|
||||
*/
|
||||
if(_perpective_correction) {
|
||||
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 */
|
||||
pr[e] = fa * pa[e] + fb * pb[e];
|
||||
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
|
||||
* uniquement l'interpolation des z */
|
||||
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
|
||||
* 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) {
|
||||
interpolate(r, a, b, fa, fb, 0, 1);
|
||||
interpolate(r, a, b, fa, fb, 6, 8);
|
||||
interpolate(r, a, b, fa, fb, 0, 1);
|
||||
interpolate(r, a, b, fa, fb, 6, 8);
|
||||
}
|
||||
|
||||
/*!\brief meta-fonction pour appeler \a interpolate, demande
|
||||
* 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) {
|
||||
interpolate(r, a, b, fa, fb, 2, 8);
|
||||
interpolate(r, a, b, fa, fb, 2, 8);
|
||||
}
|
||||
|
||||
/*!\brief meta-fonction pour appeler \a interpolate, demande
|
||||
* l'interpolation de l'ensemble des attributs */
|
||||
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) {
|
||||
return RGBA(r, g, b, a);
|
||||
return RGBA(r, g, b, a);
|
||||
}
|
||||
|
||||
GLubyte red(GLuint c) {
|
||||
return RED(c);
|
||||
return RED(c);
|
||||
}
|
||||
|
||||
GLubyte green(GLuint c) {
|
||||
return GREEN(c);
|
||||
return GREEN(c);
|
||||
}
|
||||
|
||||
GLubyte blue(GLuint c) {
|
||||
return BLUE(c);
|
||||
return BLUE(c);
|
||||
}
|
||||
|
||||
GLubyte alpha(GLuint c) {
|
||||
return ALPHA(c);
|
||||
return ALPHA(c);
|
||||
}
|
||||
|
||||
|
||||
/*!\brief au moment de quitter le programme désallouer la mémoire
|
||||
* utilisée pour _depth */
|
||||
void pquit(void) {
|
||||
if(_depth) {
|
||||
free(_depth);
|
||||
_depth = NULL;
|
||||
}
|
||||
if(_depth) {
|
||||
free(_depth);
|
||||
_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
|
||||
* réaliser un moteur de rendu DIY par rastérisation.
|
||||
*
|
||||
* \author Farès BELHADJ, amsi@up8.edu
|
||||
* \date November 17, 2021.
|
||||
* \date November 17, 2021.
|
||||
*/
|
||||
|
||||
#ifndef RASTERIZE_H_SEEN
|
||||
|
@ -19,72 +19,72 @@
|
|||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# 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 */
|
||||
enum pstate_t {
|
||||
PS_NONE = 0,
|
||||
PS_TOTALLY_OUT = 1,
|
||||
PS_PARTIALLY_OUT = 2,
|
||||
PS_CULL = 4, /* si en BACKFACE et que
|
||||
SO_CULL_BACKFACES est actif */
|
||||
PS_TOO_FAR = 8,
|
||||
PS_OUT_LEFT = 16,
|
||||
PS_OUT_RIGHT = 32,
|
||||
PS_OUT_BOTTOM = 64,
|
||||
PS_OUT_TOP = 128,
|
||||
PS_OUT_NEAR = 256,
|
||||
PS_OUT_FAR = 512
|
||||
};
|
||||
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 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 */
|
||||
};
|
||||
/*!\brief états pour les sommets ou les triangles */
|
||||
enum pstate_t {
|
||||
PS_NONE = 0,
|
||||
PS_TOTALLY_OUT = 1,
|
||||
PS_PARTIALLY_OUT = 2,
|
||||
PS_CULL = 4, /* si en BACKFACE et que
|
||||
SO_CULL_BACKFACES est actif */
|
||||
PS_TOO_FAR = 8,
|
||||
PS_OUT_LEFT = 16,
|
||||
PS_OUT_RIGHT = 32,
|
||||
PS_OUT_BOTTOM = 64,
|
||||
PS_OUT_TOP = 128,
|
||||
PS_OUT_NEAR = 256,
|
||||
PS_OUT_FAR = 512
|
||||
};
|
||||
|
||||
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 */;
|
||||
};
|
||||
};
|
||||
|
||||
struct vec2 {
|
||||
float x /* s */, y /* t */;
|
||||
};
|
||||
struct vec2 {
|
||||
float x /* s */, y /* t */;
|
||||
};
|
||||
|
||||
struct vec3 {
|
||||
struct vec3 {
|
||||
float x /* r */, y/* g */, z/* b */;
|
||||
};
|
||||
};
|
||||
|
||||
/*!\brief le sommet et l'ensemble de ses attributs */
|
||||
struct vertex_t {
|
||||
/*!\brief le sommet et l'ensemble de ses attributs */
|
||||
struct vertex_t {
|
||||
vec4 position;
|
||||
vec4 color0;
|
||||
/* début des données à partir desquelles on peut interpoler en masse */
|
||||
|
@ -92,68 +92,68 @@ extern "C" {
|
|||
vec4 icolor; /* couleur à interpoler */
|
||||
float li; /* intensité de lumière (lambertien) */
|
||||
float zmod; /* z après modelview, sert à corriger
|
||||
l'interpolation par rapport à une projection en
|
||||
perspective */
|
||||
l'interpolation par rapport à une projection en
|
||||
perspective */
|
||||
float z; /* ce z représente la depth */
|
||||
/* fin des données à partir desquelles on peut interpoler */
|
||||
vec3 normal; /* interpolez les normales si vous implémentez Phong */
|
||||
int x, y;
|
||||
enum pstate_t state;
|
||||
};
|
||||
};
|
||||
|
||||
/*!\brief le triangle */
|
||||
struct triangle_t {
|
||||
/*!\brief le triangle */
|
||||
struct triangle_t {
|
||||
vertex_t v[3];
|
||||
vec3 normal;
|
||||
vec3 normal;
|
||||
enum pstate_t state;
|
||||
};
|
||||
};
|
||||
|
||||
/*!\brief la surface englobe plusieurs triangles et des options
|
||||
* telles que le type de rendu, la couleur diffuse ou la texture.
|
||||
*/
|
||||
struct surface_t {
|
||||
/*!\brief la surface englobe plusieurs triangles et des options
|
||||
* telles que le type de rendu, la couleur diffuse ou la texture.
|
||||
*/
|
||||
struct surface_t {
|
||||
int n;
|
||||
triangle_t * t;
|
||||
GLuint tex_id;
|
||||
vec4 dcolor; /* couleur diffuse, ajoutez une couleur ambiante et
|
||||
spéculaire si vous souhaitez compléter le
|
||||
modèle */
|
||||
spéculaire si vous souhaitez compléter le
|
||||
modèle */
|
||||
soptions_t options; /* paramétrage du rendu de la surface */
|
||||
void (*interpolatefunc)(vertex_t *, vertex_t *, vertex_t *, float, float);
|
||||
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 */
|
||||
extern vertex_t vtransform(surface_t * s, vertex_t v, float * model_view_matrix, float * ti_model_view_matrix, float * projection_matrix, float * viewport);
|
||||
extern void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport);
|
||||
extern void 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 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 geometry.c */
|
||||
extern surface_t * mk_quad(void);
|
||||
extern surface_t * mk_cube(void);
|
||||
extern surface_t * mk_sphere(int longitudes, int latitudes);
|
||||
/* dans vtranform.c */
|
||||
extern vertex_t vtransform(surface_t * s, vertex_t v, float * model_view_matrix, float * ti_model_view_matrix, float * projection_matrix, float * viewport);
|
||||
extern void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport);
|
||||
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
|
||||
}
|
||||
# endif
|
||||
|
|
122
surface.c
122
surface.c
|
@ -13,14 +13,14 @@
|
|||
/*!\brief calcule le vecteur normal à un triangle */
|
||||
void tnormal(triangle_t * t) {
|
||||
vec3 u = {
|
||||
t->v[1].position.x - t->v[0].position.x,
|
||||
t->v[1].position.y - t->v[0].position.y,
|
||||
t->v[1].position.z - t->v[0].position.z
|
||||
t->v[1].position.x - t->v[0].position.x,
|
||||
t->v[1].position.y - t->v[0].position.y,
|
||||
t->v[1].position.z - t->v[0].position.z
|
||||
};
|
||||
vec3 v = {
|
||||
t->v[2].position.x - t->v[0].position.x,
|
||||
t->v[2].position.y - t->v[0].position.y,
|
||||
t->v[2].position.z - t->v[0].position.z
|
||||
t->v[2].position.x - t->v[0].position.x,
|
||||
t->v[2].position.y - t->v[0].position.y,
|
||||
t->v[2].position.z - t->v[0].position.z
|
||||
};
|
||||
MVEC3CROSS((float *)&(t->normal), (float *)&u, (float *)&v);
|
||||
MVEC3NORMALIZE((float *)&(t->normal));
|
||||
|
@ -28,40 +28,40 @@ void tnormal(triangle_t * t) {
|
|||
|
||||
/*!\brief calcule les vecteurs normaux aux triangles de la surface */
|
||||
void snormals(surface_t * s) {
|
||||
int i;
|
||||
for(i = 0; i < s->n; ++i)
|
||||
tnormal(&(s->t[i]));
|
||||
int i;
|
||||
for(i = 0; i < s->n; ++i)
|
||||
tnormal(&(s->t[i]));
|
||||
}
|
||||
|
||||
/*!\brief affecte les normales aux triangles de la surface à ses vertices */
|
||||
void tnormals2vertices(surface_t * s) {
|
||||
int 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;
|
||||
int 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;
|
||||
}
|
||||
|
||||
/*!\brief affecte l'identifiant de texture de la surface */
|
||||
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 */
|
||||
void set_diffuse_color(surface_t * s, vec4 dcolor) {
|
||||
s->dcolor = dcolor;
|
||||
s->dcolor = dcolor;
|
||||
}
|
||||
|
||||
/*!\brief active une option de la surface */
|
||||
void enable_surface_option(surface_t * s, soptions_t option) {
|
||||
if(!(s->options & option))
|
||||
s->options |= option;
|
||||
updatesfuncs(s);
|
||||
if(!(s->options & option))
|
||||
s->options |= option;
|
||||
updatesfuncs(s);
|
||||
}
|
||||
|
||||
/*!\brief désactive une option de la surface */
|
||||
void disable_surface_option(surface_t * s, soptions_t option) {
|
||||
if(s->options & option)
|
||||
s->options ^= option;
|
||||
updatesfuncs(s);
|
||||
if(s->options & option)
|
||||
s->options ^= option;
|
||||
updatesfuncs(s);
|
||||
}
|
||||
|
||||
/*!\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
|
||||
* affecte aux sommets. */
|
||||
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 };
|
||||
surface_t * s = malloc(1 * sizeof *s);
|
||||
assert(s);
|
||||
s->n = n;
|
||||
if(duplicate_triangles) {
|
||||
s->t = malloc(s->n * sizeof *(s->t));
|
||||
assert(s->t);
|
||||
memcpy(s->t, t, s->n * sizeof *(s->t));
|
||||
} else
|
||||
s->t = t;
|
||||
set_diffuse_color(s, dcolor);
|
||||
s->options = SO_DEFAULT;
|
||||
s->tex_id = 0;
|
||||
updatesfuncs(s);
|
||||
if(!has_normals) {
|
||||
snormals(s);
|
||||
tnormals2vertices(s);
|
||||
}
|
||||
return s;
|
||||
const vec4 dcolor = { 0.42f, 0.1f, 0.1f, 1.0f };
|
||||
surface_t * s = malloc(1 * sizeof *s);
|
||||
assert(s);
|
||||
s->n = n;
|
||||
if(duplicate_triangles) {
|
||||
s->t = malloc(s->n * sizeof *(s->t));
|
||||
assert(s->t);
|
||||
memcpy(s->t, t, s->n * sizeof *(s->t));
|
||||
} else
|
||||
s->t = t;
|
||||
set_diffuse_color(s, dcolor);
|
||||
s->options = SO_DEFAULT;
|
||||
s->tex_id = 0;
|
||||
updatesfuncs(s);
|
||||
if(!has_normals) {
|
||||
snormals(s);
|
||||
tnormals2vertices(s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*!\brief libère la mémoire utilisée par la surface */
|
||||
void free_surface(surface_t * s) {
|
||||
free(s->t);
|
||||
free(s);
|
||||
free(s->t);
|
||||
free(s);
|
||||
}
|
||||
/*!\brief charge et fabrique un identifiant pour une texture issue
|
||||
* d'un fichier BMP */
|
||||
GLuint get_texture_from_BMP(const char * filename) {
|
||||
GLuint id, old_id;
|
||||
/* chargement d'une image dans une surface SDL */
|
||||
SDL_Surface * s = SDL_LoadBMP(filename);
|
||||
assert(s);
|
||||
old_id = gl4dpGetTextureId(); /* au cas où */
|
||||
/* création d'un screen GL4Dummies aux dimensions de la texture */
|
||||
id = gl4dpInitScreenWithDimensions(s->w, s->h);
|
||||
/* copie de la surface SDL vers le screen en cours */
|
||||
{
|
||||
GLuint * p = gl4dpGetPixels();
|
||||
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);
|
||||
memcpy(p, d->pixels, d->w * d->h * sizeof *p);
|
||||
SDL_FreeSurface(d);
|
||||
}
|
||||
/* libération de la surface SDL */
|
||||
SDL_FreeSurface(s);
|
||||
if(old_id)
|
||||
gl4dpSetScreen(old_id);
|
||||
return id;
|
||||
GLuint id, old_id;
|
||||
/* chargement d'une image dans une surface SDL */
|
||||
SDL_Surface * s = SDL_LoadBMP(filename);
|
||||
assert(s);
|
||||
old_id = gl4dpGetTextureId(); /* au cas où */
|
||||
/* création d'un screen GL4Dummies aux dimensions de la texture */
|
||||
id = gl4dpInitScreenWithDimensions(s->w, s->h);
|
||||
/* copie de la surface SDL vers le screen en cours */
|
||||
{
|
||||
GLuint * p = gl4dpGetPixels();
|
||||
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);
|
||||
memcpy(p, d->pixels, d->w * d->h * sizeof *p);
|
||||
SDL_FreeSurface(d);
|
||||
}
|
||||
/* libération de la surface SDL */
|
||||
SDL_FreeSurface(s);
|
||||
if(old_id)
|
||||
gl4dpSetScreen(old_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
|
||||
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) {
|
||||
float dist = 1.0f;
|
||||
vec4 r1, r2;
|
||||
v.state = PS_NONE;
|
||||
MMAT4XVEC4((float *)&r1, model_view_matrix, (float *)&(v.position));
|
||||
MMAT4XVEC4((float *)&r2, projection_matrix, (float *)&r1);
|
||||
r2.x /= r2.w;
|
||||
r2.y /= r2.w;
|
||||
r2.z /= r2.w;
|
||||
r2.w = 1.0f;
|
||||
/* dist doit être à 1 ci-après */
|
||||
if(r2.x < -dist) v.state |= PS_OUT_LEFT;
|
||||
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_TOP;
|
||||
if(r2.z < -dist) v.state |= PS_OUT_NEAR;
|
||||
if(r2.z > dist) v.state |= PS_OUT_FAR;
|
||||
/* "hack" pas terrible permettant d'éviter les gros triangles
|
||||
partiellement hors-champ. Modifier dist pour jouer sur la taille
|
||||
(une fois projetés) des triangles qu'on laisse passer (plus c'est
|
||||
gros plus c'est lent avec les gros triangles). La "vraie"
|
||||
solution est obtenue en calculant l'intersection exacte entre le
|
||||
triangle et le cube unitaire ; attention, ceci produit
|
||||
potentiellement une nouvelle liste de triangles à chaque frame,
|
||||
et les attributs des sommets doivent être recalculés. */
|
||||
dist = 10.0f;
|
||||
if(r2.x < -dist || r2.x > dist || r2.y < -dist || r2.y > dist || r2.z < -dist || r2.z > dist) {
|
||||
v.state |= PS_TOO_FAR;
|
||||
float dist = 1.0f;
|
||||
vec4 r1, r2;
|
||||
v.state = PS_NONE;
|
||||
MMAT4XVEC4((float *)&r1, model_view_matrix, (float *)&(v.position));
|
||||
MMAT4XVEC4((float *)&r2, projection_matrix, (float *)&r1);
|
||||
r2.x /= r2.w;
|
||||
r2.y /= r2.w;
|
||||
r2.z /= r2.w;
|
||||
r2.w = 1.0f;
|
||||
/* dist doit être à 1 ci-après */
|
||||
if(r2.x < -dist) v.state |= PS_OUT_LEFT;
|
||||
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_TOP;
|
||||
if(r2.z < -dist) v.state |= PS_OUT_NEAR;
|
||||
if(r2.z > dist) v.state |= PS_OUT_FAR;
|
||||
/* "hack" pas terrible permettant d'éviter les gros triangles
|
||||
partiellement hors-champ. Modifier dist pour jouer sur la taille
|
||||
(une fois projetés) des triangles qu'on laisse passer (plus c'est
|
||||
gros plus c'est lent avec les gros triangles). La "vraie"
|
||||
solution est obtenue en calculant l'intersection exacte entre le
|
||||
triangle et le cube unitaire ; attention, ceci produit
|
||||
potentiellement une nouvelle liste de triangles à chaque frame,
|
||||
et les attributs des sommets doivent être recalculés. */
|
||||
dist = 10.0f;
|
||||
if(r2.x < -dist || r2.x > dist || r2.y < -dist || r2.y > dist || r2.z < -dist || r2.z > dist) {
|
||||
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;
|
||||
}
|
||||
/* 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
|
||||
|
@ -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
|
||||
* du triangle par rapport au cube unitaire.
|
||||
*
|
||||
* \see vtransform
|
||||
* \see vtransform
|
||||
* \see clip2_unit_cube
|
||||
*/
|
||||
void stransform(surface_t * s, float * model_view_matrix, float * projection_matrix, float * viewport) {
|
||||
int i, j;
|
||||
float ti_model_view_matrix[16];
|
||||
triangle_t vcull;
|
||||
/* calcul de la transposée de l'inverse de la matrice model-view
|
||||
pour la transformation des normales et le calcul du lambertien
|
||||
utilisé par le shading Gouraud dans vtransform. */
|
||||
memcpy(ti_model_view_matrix, model_view_matrix, sizeof ti_model_view_matrix);
|
||||
MMAT4INVERSE(ti_model_view_matrix);
|
||||
MMAT4TRANSPOSE(ti_model_view_matrix);
|
||||
for(i = 0; i < s->n; ++i) {
|
||||
s->t[i].state = PS_NONE;
|
||||
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);
|
||||
if(s->options & SO_CULL_BACKFACES) {
|
||||
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.z = 0.0f;
|
||||
}
|
||||
int i, j;
|
||||
float ti_model_view_matrix[16];
|
||||
triangle_t vcull;
|
||||
/* calcul de la transposée de l'inverse de la matrice model-view
|
||||
pour la transformation des normales et le calcul du lambertien
|
||||
utilisé par le shading Gouraud dans vtransform. */
|
||||
memcpy(ti_model_view_matrix, model_view_matrix, sizeof ti_model_view_matrix);
|
||||
MMAT4INVERSE(ti_model_view_matrix);
|
||||
MMAT4TRANSPOSE(ti_model_view_matrix);
|
||||
for(i = 0; i < s->n; ++i) {
|
||||
s->t[i].state = PS_NONE;
|
||||
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);
|
||||
if(s->options & SO_CULL_BACKFACES) {
|
||||
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.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 */
|
||||
void mult_matrix(float * res, float * m) {
|
||||
/* res = res x m */
|
||||
float cpy[16];
|
||||
memcpy(cpy, res, sizeof cpy);
|
||||
MMAT4XMAT4(res, cpy, m);
|
||||
/* res = res x m */
|
||||
float cpy[16];
|
||||
memcpy(cpy, res, sizeof cpy);
|
||||
MMAT4XMAT4(res, cpy, m);
|
||||
}
|
||||
|
||||
/*!\brief ajoute (multiplication droite) une translation à la matrice
|
||||
* \a m */
|
||||
void translate(float * m, float tx, float ty, float tz) {
|
||||
float mat[] = { 1.0f, 0.0f, 0.0f, tx,
|
||||
0.0f, 1.0f, 0.0f, ty,
|
||||
0.0f, 0.0f, 1.0f, tz,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
mult_matrix(m, mat);
|
||||
float mat[] = { 1.0f, 0.0f, 0.0f, tx,
|
||||
0.0f, 1.0f, 0.0f, ty,
|
||||
0.0f, 0.0f, 1.0f, tz,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
mult_matrix(m, mat);
|
||||
}
|
||||
|
||||
/*!\brief ajoute (multiplication droite) une rotation à la matrice \a
|
||||
* m */
|
||||
void rotate(float * m, float angle, float x, float y, float z) {
|
||||
float n = sqrtf(x * x + y * y + z * z);
|
||||
if ( n > 0.0f ) {
|
||||
float a, s, c, cc, x2, y2, z2, xy, yz, zx, xs, ys, zs;
|
||||
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, 1.0f };
|
||||
s = sinf ( a = (angle * (float)M_PI / 180.0f) );
|
||||
cc = 1.0f - (c = cosf ( a ));
|
||||
x /= n; y /= n; z /= n;
|
||||
x2 = x * x; y2 = y * y; z2 = z * z;
|
||||
xy = x * y; yz = y * z; zx = z * x;
|
||||
xs = x * s; ys = y * s; zs = z * s;
|
||||
mat[0] = (cc * x2) + c;
|
||||
mat[1] = (cc * xy) - zs;
|
||||
mat[2] = (cc * zx) + ys;
|
||||
/* mat[3] = 0.0f; */
|
||||
mat[4] = (cc * xy) + zs;
|
||||
mat[5] = (cc * y2) + c;
|
||||
mat[6] = (cc * yz) - xs;
|
||||
/* mat[7] = 0.0f; */
|
||||
mat[8] = (cc * zx) - ys;
|
||||
mat[9] = (cc * yz) + xs;
|
||||
mat[10] = (cc * z2) + c;
|
||||
/* mat[11] = 0.0f; */
|
||||
/* mat[12] = 0.0f; mat[= 0.0f; mat[14] = 0.0f; mat[15] = 1.0f; */
|
||||
mult_matrix(m, mat);
|
||||
}
|
||||
float n = sqrtf(x * x + y * y + z * z);
|
||||
if ( n > 0.0f ) {
|
||||
float a, s, c, cc, x2, y2, z2, xy, yz, zx, xs, ys, zs;
|
||||
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, 1.0f };
|
||||
s = sinf ( a = (angle * (float)M_PI / 180.0f) );
|
||||
cc = 1.0f - (c = cosf ( a ));
|
||||
x /= n; y /= n; z /= n;
|
||||
x2 = x * x; y2 = y * y; z2 = z * z;
|
||||
xy = x * y; yz = y * z; zx = z * x;
|
||||
xs = x * s; ys = y * s; zs = z * s;
|
||||
mat[0] = (cc * x2) + c;
|
||||
mat[1] = (cc * xy) - zs;
|
||||
mat[2] = (cc * zx) + ys;
|
||||
/* mat[3] = 0.0f; */
|
||||
mat[4] = (cc * xy) + zs;
|
||||
mat[5] = (cc * y2) + c;
|
||||
mat[6] = (cc * yz) - xs;
|
||||
/* mat[7] = 0.0f; */
|
||||
mat[8] = (cc * zx) - ys;
|
||||
mat[9] = (cc * yz) + xs;
|
||||
mat[10] = (cc * z2) + c;
|
||||
/* mat[11] = 0.0f; */
|
||||
/* mat[12] = 0.0f; mat[= 0.0f; mat[14] = 0.0f; mat[15] = 1.0f; */
|
||||
mult_matrix(m, mat);
|
||||
}
|
||||
}
|
||||
|
||||
/*!\brief ajoute (multiplication droite) un scale à la matrice \a m */
|
||||
void scale(float * m, float sx, float sy, float sz) {
|
||||
float mat[] = { sx , 0.0f, 0.0f, 0.0f,
|
||||
0.0f, sy, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, sz, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
mult_matrix(m, mat);
|
||||
float mat[] = { sx , 0.0f, 0.0f, 0.0f,
|
||||
0.0f, sy, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, sz, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
mult_matrix(m, mat);
|
||||
}
|
||||
|
||||
/*!\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) {
|
||||
float forward[3], side[3], up[3];
|
||||
float mat[] = {
|
||||
1.0f, 0.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, 0.0f, 1.0f
|
||||
};
|
||||
forward[0] = centerX - eyeX;
|
||||
forward[1] = centerY - eyeY;
|
||||
forward[2] = centerZ - eyeZ;
|
||||
up[0] = upX;
|
||||
up[1] = upY;
|
||||
up[2] = upZ;
|
||||
MVEC3NORMALIZE(forward);
|
||||
/* side = forward x up */
|
||||
MVEC3CROSS(side, forward, up);
|
||||
MVEC3NORMALIZE(side);
|
||||
/* up = side x forward */
|
||||
MVEC3CROSS(up, side, forward);
|
||||
mat[0] = side[0];
|
||||
mat[1] = side[1];
|
||||
mat[2] = side[2];
|
||||
mat[4] = up[0];
|
||||
mat[5] = up[1];
|
||||
mat[6] = up[2];
|
||||
mat[8] = -forward[0];
|
||||
mat[9] = -forward[1];
|
||||
mat[10] = -forward[2];
|
||||
mult_matrix(m, mat);
|
||||
translate(m, -eyeX, -eyeY, -eyeZ);
|
||||
float forward[3], side[3], up[3];
|
||||
float mat[] = {
|
||||
1.0f, 0.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, 0.0f, 1.0f
|
||||
};
|
||||
forward[0] = centerX - eyeX;
|
||||
forward[1] = centerY - eyeY;
|
||||
forward[2] = centerZ - eyeZ;
|
||||
up[0] = upX;
|
||||
up[1] = upY;
|
||||
up[2] = upZ;
|
||||
MVEC3NORMALIZE(forward);
|
||||
/* side = forward x up */
|
||||
MVEC3CROSS(side, forward, up);
|
||||
MVEC3NORMALIZE(side);
|
||||
/* up = side x forward */
|
||||
MVEC3CROSS(up, side, forward);
|
||||
mat[0] = side[0];
|
||||
mat[1] = side[1];
|
||||
mat[2] = side[2];
|
||||
mat[4] = up[0];
|
||||
mat[5] = up[1];
|
||||
mat[6] = up[2];
|
||||
mat[8] = -forward[0];
|
||||
mat[9] = -forward[1];
|
||||
mat[10] = -forward[2];
|
||||
mult_matrix(m, mat);
|
||||
translate(m, -eyeX, -eyeY, -eyeZ);
|
||||
}
|
||||
|
||||
/*!\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) {
|
||||
int i, oleft = 0, oright = 0, obottom = 0, otop = 0, onear = 0, ofar = 0;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
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_BOTTOM) ++obottom;
|
||||
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_FAR) ++ofar;
|
||||
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_BOTTOM) ++obottom;
|
||||
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_FAR) ++ofar;
|
||||
}
|
||||
if(!(oleft | oright | obottom | otop | onear | ofar))
|
||||
return;
|
||||
return;
|
||||
if(oleft == 3 || oright == 3 || obottom == 3 || otop == 3 || onear == 3 || ofar == 3) {
|
||||
t->state |= PS_TOTALLY_OUT;
|
||||
return;
|
||||
t->state |= PS_TOTALLY_OUT;
|
||||
return;
|
||||
}
|
||||
t->state |= PS_PARTIALLY_OUT;
|
||||
/* 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
|
||||
* exemple montre les géométries disponibles et quelques
|
||||
* transformations dessus.
|
||||
|
@ -42,172 +42,172 @@ static float _ycam = 3.0f;
|
|||
|
||||
/*!\brief paramètre l'application et lance la boucle infinie. */
|
||||
int main(int argc, char ** argv) {
|
||||
/* tentative de création d'une fenêtre pour GL4Dummies */
|
||||
if(!gl4duwCreateWindow(argc, argv, /* args du programme */
|
||||
"The DIY Rasterizer", /* titre */
|
||||
10, 10, 800, 600, /* x, y, largeur, heuteur */
|
||||
GL4DW_SHOWN) /* état visible */) {
|
||||
/* ici si échec de la création souvent lié à un problème d'absence
|
||||
* de contexte graphique ou d'impossibilité d'ouverture d'un
|
||||
* contexte OpenGL (au moins 3.2) */
|
||||
return 1;
|
||||
}
|
||||
init();
|
||||
/* mettre en place la fonction d'interception clavier */
|
||||
gl4duwKeyDownFunc(key);
|
||||
/* mettre en place la fonction de display */
|
||||
gl4duwDisplayFunc(draw);
|
||||
/* boucle infinie pour éviter que le programme ne s'arrête et ferme
|
||||
* la fenêtre immédiatement */
|
||||
gl4duwMainLoop();
|
||||
return 0;
|
||||
/* tentative de création d'une fenêtre pour GL4Dummies */
|
||||
if(!gl4duwCreateWindow(argc, argv, /* args du programme */
|
||||
"The DIY Rasterizer", /* titre */
|
||||
10, 10, 800, 600, /* x, y, largeur, heuteur */
|
||||
GL4DW_SHOWN) /* état visible */) {
|
||||
/* ici si échec de la création souvent lié à un problème d'absence
|
||||
* de contexte graphique ou d'impossibilité d'ouverture d'un
|
||||
* contexte OpenGL (au moins 3.2) */
|
||||
return 1;
|
||||
}
|
||||
init();
|
||||
/* mettre en place la fonction d'interception clavier */
|
||||
gl4duwKeyDownFunc(key);
|
||||
/* mettre en place la fonction de display */
|
||||
gl4duwDisplayFunc(draw);
|
||||
/* boucle infinie pour éviter que le programme ne s'arrête et ferme
|
||||
* la fenêtre immédiatement */
|
||||
gl4duwMainLoop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!\brief init de nos données, spécialement les trois surfaces
|
||||
* utilisées dans ce code */
|
||||
void init(void) {
|
||||
GLuint id;
|
||||
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
|
||||
* pouvons dessiner) aux dimensions de la fenêtre. IMPORTANT de
|
||||
* créer le screen avant d'utiliser les fonctions liées au
|
||||
* textures */
|
||||
gl4dpInitScreen();
|
||||
/* Pour forcer la désactivation de la synchronisation verticale */
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
/* on créé nos trois type de surfaces */
|
||||
_quad = mk_quad(); /* ça fait 2 triangles */
|
||||
_cube = mk_cube(); /* ça fait 2x6 triangles */
|
||||
_sphere = mk_sphere(12, 12); /* ça fait 12x12x2 trianles ! */
|
||||
/* on change les couleurs de surfaces */
|
||||
_quad->dcolor = r; _cube->dcolor = b; _sphere->dcolor = g;
|
||||
/* on leur rajoute à toutes la même texture */
|
||||
id = get_texture_from_BMP("images/tex.bmp");
|
||||
set_texture_id( _quad, id);
|
||||
set_texture_id( _cube, id);
|
||||
set_texture_id(_sphere, id);
|
||||
/* si _use_tex != 0, on active l'utilisation de la texture pour les
|
||||
* trois */
|
||||
if(_use_tex) {
|
||||
enable_surface_option( _quad, SO_USE_TEXTURE);
|
||||
enable_surface_option( _cube, SO_USE_TEXTURE);
|
||||
enable_surface_option(_sphere, SO_USE_TEXTURE);
|
||||
}
|
||||
/* si _use_lighting != 0, on active l'ombrage */
|
||||
if(_use_lighting) {
|
||||
enable_surface_option( _quad, SO_USE_LIGHTING);
|
||||
enable_surface_option( _cube, SO_USE_LIGHTING);
|
||||
enable_surface_option(_sphere, SO_USE_LIGHTING);
|
||||
}
|
||||
/* on désactive le back cull face pour le quadrilatère, ainsi on
|
||||
* peut voir son arrière quand le lighting est inactif */
|
||||
disable_surface_option(_quad, SO_CULL_BACKFACES);
|
||||
/* mettre en place la fonction à appeler en cas de sortie */
|
||||
atexit(sortie);
|
||||
GLuint id;
|
||||
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
|
||||
* pouvons dessiner) aux dimensions de la fenêtre. IMPORTANT de
|
||||
* créer le screen avant d'utiliser les fonctions liées au
|
||||
* textures */
|
||||
gl4dpInitScreen();
|
||||
/* Pour forcer la désactivation de la synchronisation verticale */
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
/* on créé nos trois type de surfaces */
|
||||
_quad = mk_quad(); /* ça fait 2 triangles */
|
||||
_cube = mk_cube(); /* ça fait 2x6 triangles */
|
||||
_sphere = mk_sphere(12, 12); /* ça fait 12x12x2 trianles ! */
|
||||
/* on change les couleurs de surfaces */
|
||||
_quad->dcolor = r; _cube->dcolor = b; _sphere->dcolor = g;
|
||||
/* on leur rajoute à toutes la même texture */
|
||||
id = get_texture_from_BMP("images/tex.bmp");
|
||||
set_texture_id( _quad, id);
|
||||
set_texture_id( _cube, id);
|
||||
set_texture_id(_sphere, id);
|
||||
/* si _use_tex != 0, on active l'utilisation de la texture pour les
|
||||
* trois */
|
||||
if(_use_tex) {
|
||||
enable_surface_option( _quad, SO_USE_TEXTURE);
|
||||
enable_surface_option( _cube, SO_USE_TEXTURE);
|
||||
enable_surface_option(_sphere, SO_USE_TEXTURE);
|
||||
}
|
||||
/* si _use_lighting != 0, on active l'ombrage */
|
||||
if(_use_lighting) {
|
||||
enable_surface_option( _quad, SO_USE_LIGHTING);
|
||||
enable_surface_option( _cube, SO_USE_LIGHTING);
|
||||
enable_surface_option(_sphere, SO_USE_LIGHTING);
|
||||
}
|
||||
/* on désactive le back cull face pour le quadrilatère, ainsi on
|
||||
* peut voir son arrière quand le lighting est inactif */
|
||||
disable_surface_option(_quad, SO_CULL_BACKFACES);
|
||||
/* mettre en place la fonction à appeler en cas de sortie */
|
||||
atexit(sortie);
|
||||
}
|
||||
|
||||
/*!\brief la fonction appelée à chaque display. */
|
||||
void draw(void) {
|
||||
static float a = 0.0f;
|
||||
float model_view_matrix[16], projection_matrix[16], nmv[16];
|
||||
/* effacer l'écran et le buffer de profondeur */
|
||||
gl4dpClearScreen();
|
||||
clear_depth_map();
|
||||
/* des macros facilitant le travail avec des matrices et des
|
||||
* vecteurs se trouvent dans la bibliothèque GL4Dummies, dans le
|
||||
* fichier gl4dm.h */
|
||||
/* charger un frustum dans projection_matrix */
|
||||
MFRUSTUM(projection_matrix, -0.05f, 0.05f, -0.05f, 0.05f, 0.1f, 1000.0f);
|
||||
/* charger la matrice identité dans model-view */
|
||||
MIDENTITY(model_view_matrix);
|
||||
/* 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);
|
||||
/* 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 */
|
||||
translate(nmv, -3.0f, 0.0f, 0.0f);
|
||||
rotate(nmv, a, 1.0f, 0.0f, 0.0f);
|
||||
transform_n_rasterize(_quad, nmv, projection_matrix);
|
||||
/* 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 */
|
||||
translate(nmv, 3.0f, 0.0f, 0.0f);
|
||||
rotate(nmv, a, 0.0f, 0.0f, 1.0f);
|
||||
transform_n_rasterize(_cube, nmv, projection_matrix);
|
||||
/* 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 */
|
||||
rotate(nmv, a, 0.0f, 1.0f, 0.0f);
|
||||
transform_n_rasterize(_sphere, nmv, projection_matrix);
|
||||
/* déclarer qu'on a changé des pixels du screen (en bas niveau) */
|
||||
gl4dpScreenHasChanged();
|
||||
/* fonction permettant de raffraîchir l'ensemble de la fenêtre*/
|
||||
gl4dpUpdateScreen(NULL);
|
||||
a += 0.1f;
|
||||
static float a = 0.0f;
|
||||
float model_view_matrix[16], projection_matrix[16], nmv[16];
|
||||
/* effacer l'écran et le buffer de profondeur */
|
||||
gl4dpClearScreen();
|
||||
clear_depth_map();
|
||||
/* des macros facilitant le travail avec des matrices et des
|
||||
* vecteurs se trouvent dans la bibliothèque GL4Dummies, dans le
|
||||
* fichier gl4dm.h */
|
||||
/* charger un frustum dans projection_matrix */
|
||||
MFRUSTUM(projection_matrix, -0.05f, 0.05f, -0.05f, 0.05f, 0.1f, 1000.0f);
|
||||
/* charger la matrice identité dans model-view */
|
||||
MIDENTITY(model_view_matrix);
|
||||
/* 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);
|
||||
/* 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 */
|
||||
translate(nmv, -3.0f, 0.0f, 0.0f);
|
||||
rotate(nmv, a, 1.0f, 0.0f, 0.0f);
|
||||
transform_n_rasterize(_quad, nmv, projection_matrix);
|
||||
/* 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 */
|
||||
translate(nmv, 3.0f, 0.0f, 0.0f);
|
||||
rotate(nmv, a, 0.0f, 0.0f, 1.0f);
|
||||
transform_n_rasterize(_cube, nmv, projection_matrix);
|
||||
/* 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 */
|
||||
rotate(nmv, a, 0.0f, 1.0f, 0.0f);
|
||||
transform_n_rasterize(_sphere, nmv, projection_matrix);
|
||||
/* déclarer qu'on a changé des pixels du screen (en bas niveau) */
|
||||
gl4dpScreenHasChanged();
|
||||
/* fonction permettant de raffraîchir l'ensemble de la fenêtre*/
|
||||
gl4dpUpdateScreen(NULL);
|
||||
a += 0.1f;
|
||||
}
|
||||
|
||||
/*!\brief intercepte l'événement clavier pour modifier les options. */
|
||||
void key(int keycode) {
|
||||
switch(keycode) {
|
||||
case GL4DK_UP:
|
||||
_ycam += 0.05f;
|
||||
break;
|
||||
case GL4DK_DOWN:
|
||||
_ycam -= 0.05f;
|
||||
break;
|
||||
case GL4DK_t: /* 't' la texture */
|
||||
_use_tex = !_use_tex;
|
||||
if(_use_tex) {
|
||||
enable_surface_option( _quad, SO_USE_TEXTURE);
|
||||
enable_surface_option( _cube, SO_USE_TEXTURE);
|
||||
enable_surface_option(_sphere, SO_USE_TEXTURE);
|
||||
} else {
|
||||
disable_surface_option( _quad, SO_USE_TEXTURE);
|
||||
disable_surface_option( _cube, SO_USE_TEXTURE);
|
||||
disable_surface_option(_sphere, SO_USE_TEXTURE);
|
||||
switch(keycode) {
|
||||
case GL4DK_UP:
|
||||
_ycam += 0.05f;
|
||||
break;
|
||||
case GL4DK_DOWN:
|
||||
_ycam -= 0.05f;
|
||||
break;
|
||||
case GL4DK_t: /* 't' la texture */
|
||||
_use_tex = !_use_tex;
|
||||
if(_use_tex) {
|
||||
enable_surface_option( _quad, SO_USE_TEXTURE);
|
||||
enable_surface_option( _cube, SO_USE_TEXTURE);
|
||||
enable_surface_option(_sphere, SO_USE_TEXTURE);
|
||||
} else {
|
||||
disable_surface_option( _quad, SO_USE_TEXTURE);
|
||||
disable_surface_option( _cube, 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. */
|
||||
void sortie(void) {
|
||||
/* on libère nos trois surfaces */
|
||||
if(_quad) {
|
||||
free_surface(_quad);
|
||||
_quad = NULL;
|
||||
}
|
||||
if(_cube) {
|
||||
free_surface(_cube);
|
||||
_cube = NULL;
|
||||
}
|
||||
if(_sphere) {
|
||||
free_surface(_sphere);
|
||||
_sphere = NULL;
|
||||
}
|
||||
/* libère tous les objets produits par GL4Dummies, ici
|
||||
* principalement les screen */
|
||||
gl4duClean(GL4DU_ALL);
|
||||
/* on libère nos trois surfaces */
|
||||
if(_quad) {
|
||||
free_surface(_quad);
|
||||
_quad = NULL;
|
||||
}
|
||||
if(_cube) {
|
||||
free_surface(_cube);
|
||||
_cube = NULL;
|
||||
}
|
||||
if(_sphere) {
|
||||
free_surface(_sphere);
|
||||
_sphere = NULL;
|
||||
}
|
||||
/* libère tous les objets produits par GL4Dummies, ici
|
||||
* principalement les screen */
|
||||
gl4duClean(GL4DU_ALL);
|
||||
}
|
||||
|
|
Reference in a new issue