Projet de géométrie solide constructive en langage C
Projet de géométrie solide constructive en langage C
Cet article propose en détaille un petit projet de géométrie solide constructive en langage C
Vous pourrez télécharger le fichier au format zip il contient le code sources complet avec support.
Extrait du code :
// includes
#include "glut.h"
#include <math.h>
#include "trackball.h"
// defines
#define SPHERE 1
#define CONE 2
#define CUBE 3
// opération CSG (Constructive Solid Geometry) Traduction: Géométrie solide constructive
// types d'opérations CSG
typedef enum {
CSG_A,
CSG_B,
CSG_A_OR_B,
CSG_A_AND_B,
CSG_A_SUB_B,
CSG_B_SUB_A
} csgOperation;
// globals
GLint Width;
GLint Height;
GLfloat zoom = 0.0;
GLboolean cube_picked = GL_FALSE;
GLboolean sphere_picked = GL_FALSE;
GLboolean cone_picked = GL_FALSE;
GLboolean selection = GL_FALSE; // rendu dans la sélection du tampon
#define SELECT_BUFFER 32
GLuint select_buffer[SELECT_BUFFER]; // tampon de sélection
GLfloat cone_x = 0.0;
GLfloat cone_y = 0.0;
GLfloat cone_z = 0.0;
GLfloat cube_x = 0.0;
GLfloat cube_y = 0.0;
GLfloat cube_z = 0.0;
GLfloat sphere_x = 0.0;
GLfloat sphere_y = 0.0;
GLfloat sphere_z = 0.0;
GLint mouse_state = -1;
GLint mouse_button = -1;
csgOperation Op = CSG_A_OR_B;
void (*A)(void);
void (*B)(void);
// les fonctions
// un()
// dessiner un seul objet
void one(void(*a)(void))
{
glEnable(GL_DEPTH_TEST);
a();
glDisable(GL_DEPTH_TEST);
}
// ou()
// booléen A ou B (dessiner où A ou B)
// algorithme: simple, il suffit de dessiner les deux avec le test de profondeur activé
void or(void(*a)(void), void(*b)())
{
glPushAttrib(GL_ALL_ATTRIB_BITS); // À FAIRE - devrait juste pousser la profondeur
glEnable(GL_DEPTH_TEST);
a(); b();
glPopAttrib();
}
// intérieur()
// définit le tampon de gabarit pour montrer la partie de A
// (face avant ou arrière selon 'face')
// qui est à l'intérieur de B
void inside(void(*a)(void), void(*b)(void), GLenum face, GLenum test)
{
// dessine A dans le tampon de profondeur, mais pas dans le tampon de couleur
glEnable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glCullFace(face);
a();
// utilisez le tampon de pochoir pour trouver les parties de A qui sont à l'intérieur de B
// en commençant par incrémenter le tampon pochoir partout où les faces avant de B sont...
glDepthMask(GL_FALSE);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glCullFace(GL_BACK);
b();
// ...puis décrémenter le tampon de pochoir partout où les faces arrière de B sont
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
glCullFace(GL_FRONT);
b();
// dessine maintenant la partie de A qui est à l'intérieur de B
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(test, 0, 1);
glDisable(GL_DEPTH_TEST);
glCullFace(face);
a();
// réinitialiser le test du pochoir
glDisable(GL_STENCIL_TEST);
}
// correction()
// corrige le tampon de profondeur avec les valeurs de profondeur de A
void fixup(void(*a)(void))
{
// corrige le tampon de profondeur
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDepthFunc(GL_ALWAYS);
a();
// réinitialiser la fonction de profondeur
glDepthFunc(GL_LESS);
}
// et()
// Booléen A et B (dessinez chaque fois que A coupe B)
// algorithme: trouver où A est à l'intérieur de B, puis trouver où
// B est à l'intérieur de A
void and(void(*a)(void), void(*b)(void))
{
inside(a, b, GL_BACK, GL_NOTEQUAL);
#if 1
fixup(b);
#endif
inside(b, a, GL_BACK, GL_NOTEQUAL);
}
// soustraction()
// booléen A soustraire B (dessiner partout où A est et B n'est pas)
// algorithme: trouver où A est à l'intérieur de B, puis trouver où
// les faces arrières de B ne sont pas en A
void sub(void(*a)(void), void(*b)(void))
{
inside(a, b, GL_FRONT, GL_NOTEQUAL);
#if 1
fixup(b);
#endif
inside(b, a, GL_BACK, GL_EQUAL);
}
// sphère()
// dessiner une sphère jaune
void sphere(void)
{
glLoadName(2);
glPushMatrix();
glTranslatef(sphere_x, sphere_y, sphere_z);
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(5.0, 16, 16);
glPopMatrix();
}
// cube()
// dessiner un cube rouge
void cube(void)
{
glLoadName(1);
glPushMatrix();
glTranslatef(cube_x, cube_y, cube_z);
glColor3f(1.0, 0.0, 0.0);
glutSolidCube(8.0);
glPopMatrix();
}
// cône()
// dessiner un cône vert
void cone(void)
{
glLoadName(3);
glPushMatrix();
glTranslatef(cone_x, cone_y, cone_z);
glColor3f(0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -6.5);
glutSolidCone(4.0, 15.0, 16, 16);
glRotatef(180.0, 1.0, 0.0, 0.0);
glutSolidCone(4.0, 0.0, 16, 1);
glPopMatrix();
}