Outillage DCC / Addon Blender

BlenderCube

Addon Rubik's Cube paramétrique pour Blender

BlenderPythonbpyAddonRigging

L'idée

Je voulais me confronter sérieusement à l’API Python de Blender en livrant un addon complet plutôt qu’un script jetable. Il couvre la génération de mesh, les matériaux et un rig animable, avec une architecture propre.

L’addon se compose de trois modules et se pilote depuis le panneau latéral de Blender. Il s’installe comme n’importe quel addon.

Génération paramétrique

L’opérateur OP_CreateRubik est le point d’entrée principal. Il expose quatre propriétés dans le panneau Blender :

  • grid : nombre de cubes par axe (2 à 5, donc 2x2x2 jusqu’à 5x5x5)
  • size : taille globale du cube en unités Blender
  • spacing : écart entre les petits cubes
  • bevel_offset : rayon du biseau sur les arêtes

La géométrie est construite via bmesh : chaque petit cube est créé individuellement, biseauté, puis le shading lissé est appliqué automatiquement. Tout se recalcule à partir de la taille globale. Passer d’un 2x2 à un 5x5 ne demande pas de toucher au code, juste de changer grid dans le panneau.

Matériaux par face

material_tools.py s’occupe de la coloration. Il parcourt le maillage en mode édition, repère les faces dont la normale pointe vers l’extérieur du cube global et leur assigne la bonne couleur.

Six directions, six Principled BSDF :

  • haut : blanc
  • bas : jaune
  • avant : rouge
  • arrière : orange
  • gauche : bleu
  • droite : vert

Les faces internes (entre deux petits cubes adjacents) restent neutres, comme sur un vrai Rubik’s.

Rig avec contraintes Child Of

C’est la partie la plus dense techniquement. Je crée une armature racine à laquelle je parente chaque petit cube, puis je place trois séries de bones contrôleurs le long des axes X, Y et Z.

Pour chaque petit cube, apply_child_of_constraints cherche dynamiquement le contrôleur le plus proche sur chaque axe. La distance est calculée entre le centre de géométrie du cube et la tête du bone en espace monde.

Une fois le bon contrôleur trouvé, j’ajoute une contrainte Child Of réglée ainsi :

  • copie uniquement la rotation de l’axe concerné
  • translations et échelle désactivées
  • rotations parasites verrouillées sur les contrôleurs

Tourner le bone contrôleur d’une tranche n’entraîne donc que les cubes de cette tranche.

Architecture dual-mode script/addon

Le point d’entrée __init__.py détecte son contexte au démarrage :

En mode script (développement) :

  • injecte le dossier courant dans sys.path
  • recharge les modules modifiés avec importlib.reload
  • appelle register() manuellement pour itérer sans réinstaller

En mode addon (installé via Blender) :

  • déclare bl_info (nom, version, catégorie)
  • passe par les imports relatifs Blender standards
  • register() et unregister() sont appelés par Blender lui-même

La détection se fait avec if __name__ == "__main__" pour le mode script, sinon on part sur les imports relatifs. Un seul fichier d’entrée suffit.

Limite assumée

Le rig a une limite : la sélection par proximité ne fonctionne que sur la pose de repos et ne suit pas les rotations cumulées.

Une fois une tranche tournée, l’armature continue de se baser sur les positions de repos des centres de géométrie. Enchaîner deux rotations librement, comme sur un vrai Rubik’s, n’est donc pas possible avec cette approche.

Je ne l’ai pas traitée, c’était hors de la portée du projet, et je l’ai documentée plutôt que cachée. Le résoudre demanderait de recalculer les appartenances aux tranches après chaque rotation, ou de passer par un système de groupes dynamiques.

DCC tooling / Blender addon

BlenderCube

Parametric Rubik's Cube addon

BlenderPythonbpyAddonRigging

The idea

BlenderCube is a side project I built over a single weekend in 2024. I wanted to throw myself at Blender’s Python API under real time pressure and deliver a working end-to-end addon (mesh generation, materials, rig) with a clean architecture, despite the short timeframe.

Parametric generation

The OP_CreateRubik operator has grid, size, spacing and bevel_offset properties and builds an NxNxN grid of cubes via bmesh, applying bevel and smooth shading automatically. All geometry derives from the global size, so going from a 2x2 to a 5x5 needs no code change.

Per-face materials

Materials are assigned face by face, depending on where each cube sits in the grid. material_tools.py walks the mesh in edit mode and selects faces whose normal points in one of six directions (top, bottom, front, back, left, right). Each direction gets its own colored Principled BSDF (white, yellow, red, orange, blue, green), but only on faces that point outward on the full cube.

Rig with Child Of constraints

The rig is the most interesting part technically. I create a root armature, parent every small cube to it, then place three sets of controller bones (X, Y, Z) along each axis.

For every cube, apply_child_of_constraints dynamically finds the closest controller on each axis (by world-space distance between the cube’s geometry center and the bone head) and adds a Child Of constraint that only copies rotation on the relevant axis. Translation and scale are disabled, and stray rotations are locked on the controllers themselves.

Dual-mode script vs addon

The __init__.py entry point detects whether it runs as a script (__name__ == "__main__") or as an installed addon. In script mode it injects a path into sys.path, reloads modules with importlib.reload and calls register() for fast iteration. In addon mode it declares bl_info and uses Blender’s standard relative imports.

Acknowledged limitation

The rig isn’t finalized: the proximity-based assignment works on the rest pose but doesn’t track cumulative rotations, so layer moves can’t be freely chained the way a real Rubik’s would allow. That was out of scope for the weekend, and it’s documented.