Fonctionnalités essentielles d’un CAD
Un outil de conception assistée par ordinateur doit impérativement disposer de trois composantes : une structure de données décrivant le modèle tridimensionnel, un moteur d’affichage capable de projeter ce modèle sur un écran 2D, et une interface d’interaction permettant d’ajouter ou de modifier les géométries. Le texte indique que le projet implémente ces trois exigences en Python, en s’appuyant sur une représentation interne basée sur des matrices 4×4 (créées avec numpy.identity(4)) pour stocker la transformation du modèle et la vue inverse.
En plus de ces bases, le texte rappelle que les CAD spécialisés intègrent des modules supplémentaires (simulation climatique, vérification d’impression 3D, simulation électrique, etc.). Le modélisateur présenté ne propose pas ces extensions, mais il conserve la capacité de sauvegarder et charger les scènes, ce qui est indispensable pour la collaboration et la persistance des travaux.
Architecture du modélisateur 3D en Python
Le cœur du programme est la classe Viewer. Son constructeur invoque successivement init_interface, init_opengl, init_scene et init_interaction, puis init_primitives. init_interface crée une fenêtre de 640 × 480 pixels via glutInitWindowSize(640, 480) et enregistre la fonction de rendu avec glutDisplayFunc(self.render). Le rendu s’appuie sur le pipeline fixe d’OpenGL Legacy : activation du culling arrière (glEnable(GL_CULL_FACE), glCullFace(GL_BACK)), du test de profondeur (glEnable(GL_DEPTH_TEST), glDepthFunc(GL_LESS)) et d’une source lumineuse (glEnable(GL_LIGHT0)). Cette configuration minimise le code nécessaire pour obtenir une visualisation correcte, au prix d’une absence de shaders programmables.
class Viewer(object):
def __init__(self):
""" Initialize the viewer. """
self.init_interface()
self.init_opengl()
self.init_scene()
self.init_interaction()
init_primitives()
def init_interface(self):
""" initialize the window and register the render function """
glutInit()
glutInitWindowSize(640, 480)
glutCreateWindow("3D Modeller")
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
glutDisplayFunc(self.render)
def init_opengl(self):
""" initialize the opengl settings to render the scene """
self.inverseModelView = numpy.identity(4)
self.modelView = numpy.identity(4)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LESS)
glEnable(GL_LIGHT0)…Après l’initialisation, le programme transfère le contrôle à glutMainLoop(), qui ne retourne jamais. Toutes les interactions (clavier, souris) sont gérées par des callbacks enregistrés dans init_interaction, garantissant une boucle d’événements réactive sans logique de boucle explicite dans le code utilisateur.
Choix techniques et limites
L’utilisation d’OpenGL Legacy, bien que dépréciée, répond à l’objectif de rester sous la barre des 500 lignes. Le pipeline fixe élimine la nécessité d’écrire des shaders GLSL, ce qui réduit la charge de travail en algèbre linéaire et en gestion de programmes GPU. Cependant, ce choix impose des limites : aucune optimisation moderne (tessellation, compute shaders) n’est disponible, et la performance sur du matériel récent peut être inférieure à celle d’une implémentation basée sur le pipeline programmable.
GLUT, fourni avec OpenGL, simplifie la création de fenêtres et l’enregistrement de callbacks, mais il ne propose pas de fonctionnalités avancées comme le support multi‑fenêtres, le DPI scaling ou l’intégration native avec les environnements de bureau. Des alternatives telles que GTK ou Qt offriraient ces capacités, au coût d’une complexité accrue et d’un volume de code supérieur.
En résumé, le projet démontre qu’il est possible de construire un modélisateur 3D fonctionnel en Python avec moins de 500 lignes, en privilégiant des API graphiques legacy et un gestionnaire de fenêtres minimaliste. Cette approche convient à l’apprentissage ou à la prototypisation rapide, mais elle ne doit pas être confondue avec une solution prête pour la production, où la modernité du pipeline graphique et la robustesse de la couche UI sont essentielles.