BlenderPocket - Mon portage de Blender 3D sur mobile (PDA/PocketPC) dans les années 2000
Genèse du projet
En tant que directeur de projets IT et Data, mon rôle quotidien s’oriente vers la coordination d’équipes et l’alignement des architectures sur les enjeux métiers. Toutefois, je considère qu’une pratique technique régulière reste indispensable pour maintenir une expertise pointue.
Au début de ma carrière, j’ai lancé le projet BlenderPocket qui fut l’aboutissement de cette démarche. Développé intégralement sur mon temps libre, il répondait à un défi technique ambitieux. Voici la synthèse de ce travail de portage.
Le code plutôt que de longs discours : l’intégralité du code source de ce projet personnel est ouvert et disponible sur mon GitHub.
Le point de départ
Ma rencontre avec Blender remonte à 2002. Je cherchais à m’initier à la 3D et je suis tombé sur blender.free.fr, qui était à l’époque la référence francophone incontournable. J’ai rapidement appris à adorer ce logiciel — sa puissance, sa communauté, son architecture ouverte.
Quelques années plus tard, j’ai fait l’acquisition d’un PDA/PocketPC. Et une idée a commencé à germer : pourrais-je y faire tourner Blender ? Avoir toute une suite 3D dans la poche…
NaN, la société à l’origine de Blender, avait déjà tenté l’expérience sur un iPaq. Mais leur version était ancienne et le code source de ce travail n’était pas disponible. Par contre, le code source de Blender lui-même était déjà structuré pour faciliter ce type de portage. Les vrais problèmes de fond avaient été anticipés. Il restait “juste” à les résoudre.
Briser le tabou de la “3D réservée aux machines puissantes” m’a semblé être une excellente raison de m’y mettre.
Premiers pas et analyse des contraintes
Autant être honnête : mes connaissances en programmation étaient à l’époque assez faibles, ou du moins très académiques. Mes connaissances en OpenGL étaient inexistantes, et mon expertise des PDA/PocketPC se résumait à celle d’un utilisateur lambda.
J’ai rejoint la mailing list de développement de Blender et j’y ai posé mes questions très simplement. À ma grande surprise, Ton Roosendaal, le créateur original de Blender, m’a répondu directement. Il a pris le temps de m’écrire en détail. Son mail était à la fois un avertissement et une feuille de route pointant trois obstacles majeurs :
- La librairie interne Ghost (gestion des interfaces) allait devoir être réécrite pour WinCE.
- OpenGL était au cœur de Blender. Et les PDA/PocketPC de l’époque ne le supportaient pas nativement.
- Les PDA/PocketPC sont mauvais en calcul à virgule flottante. Ce qui posait des problèmes sérieux pour OpenGL, le son et le Game Engine.
Ma lecture de ce mail à l’époque : Ghost, je ne savais pas ce que c’était. OpenGL, j’allais devoir trouver de l’aide. La virgule flottante, j’allais sabrer le son et le Game Engine et on en reparlerait.
C’est parti comme ça.
Adaptation de la librairie Ghost (gestion des interfaces)
Ghost est la couche d’abstraction entre le hardware et les premières couches logicielles de Blender. Elle gère :
- le stylus (l’équivalent de la souris sur PDA/PocketPC)
- le clavier
- les fenêtres
- les événements
- l’initialisation d’OpenGL
C’est une librairie de taille modeste, ce qui en faisait un bon point d’entrée pour apprendre la programmation sur PDA/PocketPC. L’auteur original avait utilisé de la programmation orientée objet, je n’avais donc pas tout à réécrire. Il suffisait d’adapter la partie Win32, les interfaces étant compatibles avec WinCE.
La sueur a coulé. Le code a fini par compiler.
Mais pour tester Ghost, il me fallait de l’OpenGL afin d’avoir des éléments à contrôler. Et c’est là que ça s’est compliqué.
Le défi OpenGL ES
Les PDA/PocketPC de l’époque ne parlaient pas OpenGL mais supportaient OpenGL ES, un sous-ensemble plus limité. Le vocabulaire de base était le même, mais il manquait des pièces essentielles : pas de primitives de type “Quads”, pas de dessin de pixels directs, pas de sélection, pas de feedback et surtout : pas de glBegin ni de glEnd. Pour OpenGL, c’est comme retirer les verbes “être” et “avoir” de la langue française. On ne pouvait pas aller bien loin.
J’ai hanté les forums : “Quelqu’un peut-il m’expliquer comment émuler begin/end en OpenGL ES ?” C’est là qu’est intervenu Daniel Wagner. Il m’a généreusement donné accès à sa librairie KlimtES, qui implémentait les fonctions OpenGL manquantes par-dessus OpenGL ES. Sa seule condition : ne pas diffuser son code source, qui n’était pas encore libre.
Avec KlimtES, j’ai pu voir mes premières Suzanne (la tête de singe, mascotte de Blender) tourner sur mon PDA/PocketPC. Tester le clic au stylus. Valider toutes les fonctionnalités de Ghost. La première étape était franchie.
Mais KlimtES avait une limite : son code était fermé. Pas question de le redistribuer ni de le modifier librement. J’allais devoir, à terme, écrire ma propre solution.
Compilation et gestion de la mémoire
Après Ghost, j’ai bataillé avec Python sur PDA/PocketPC. Puis BlenderPocket a finalement compilé sur l’ensemble du projet.
Il compilait, oui, mais plantait immédiatement ! Le tout avec un message d’erreur que je ne comprenais pas : “données mal alignées”.
Ce qui a suivi fut une plongée dans les entrailles de la gestion mémoire de Blender. La librairie guardedalloc — dont les commentaires étaient encore en néerlandais. Les structures SDNA. Un territoire assez hostile.
Après des semaines d’investigation, j’ai trouvé la vraie cause de ce problème : une simple mauvaise allocation mémoire, et non un problème fondamental d’alignement. Mais je ne le savais pas encore… Et avant d’arriver à cette conclusion, j’ai eu le temps de commettre deux erreurs mémorables.
Résolution des principaux obstacles techniques
La problématique de l’encodage Unicode
Toute la documentation sur le portage vers PDA/PocketPC martelait la même chose : “WinCE fonctionne en Unicode”. J’avais alors compris qu’il fallait convertir tout Blender en Unicode. Très mauvaise interprétation.
Je me suis donc mis à remplacer chaque char par des wchar_t dans le code de Blender. J’ai modifié les fonctions de chaînes de caractères. Je suis descendu jusqu’aux tréfonds de guardedalloc, en lisant péniblement des commentaires en néerlandais. J’étais en train de saccager l’architecture du logiciel. Mais de la découvrir dans ses plus profondes subtilités aussi, ce qui me servira plus tard dans le projet.
Les développeurs sur la mailing list m’ont arrêté net. J’ai pris du recul et compris mon erreur : le système d’exploitation impose l’Unicode uniquement pour ses appels API natifs — CreateWindow() et consorts. Le cœur de Blender pouvait très bien rester en ANSI. Il suffisait de faire la conversion juste avant d’appeler les fonctions de l’OS.
J’ai jeté 60 % de mon travail à la poubelle. Et j’ai recommencé proprement.
L’erreur d’alignement mémoire
Quand Blender plantait avec une erreur d’alignement mémoire, j’ai commencé à investiguer les spécificités ARM, l’alignement des structures, les mécanismes internes de SDNA. Fascinant. Et complètement hors sujet.
La vraie cause : une mauvaise allocation mémoire à un endroit précis. Rien de plus. Il a alors suffi de générer correctement dna.c directement depuis le PDA/PocketPC, une merveille de conception côté Blender assurant la compatibilité des structures de données quelle que soit l’architecture des processeurs. Tout simplement magnifique.
Ces deux erreurs cumulées m’ont coûté plusieurs mois. La leçon : avant de sortir le bazooka, vérifier qu’on n’a pas juste une mouche à chasser.
Développement d’un wrapper OpenGL ES personnalisé
KlimtES avait permis les premiers tests, mais je ne pouvais pas l’utiliser en production, son code source étant fermé. J’ai donc écrit mon propre wrapper : OGLES2OGL.
Le principe : implémenter par-dessus OpenGL ES toutes les fonctions OpenGL manquantes dont Blender avait besoin. La liste était précise :
glBegin/glEnd- les primitives
GL_QUADS(absentes d’OpenGL ES) - le dessin de pixels (
glDrawPixels,glBitmap) - les mécanismes de sélection et de feedback
glDrawBuffer/glReadBuffer- les évaluateurs
Pour les primitives manquantes, je me suis inspiré des travaux open source disponibles, notamment le portage de Quake III pour PDA/PocketPC. Aucune ligne n’est issue de KlimtES.
Aujourd’hui, le wrapper fonctionne pour toutes les fonctions nécessaires à Blender, à l’exception des évaluateurs qui sont implémentés de façon simplifiée. Il est disponible sur mon GitHub dans le code source de BlenderPocket.
Pour le moteur OpenGL ES lui-même, j’ai évalué plusieurs options : Mesa3d (trop lent sur ARM sans refonte en virgule fixe), Klimt (open source mais limité), Vincent (instable à l’époque), et finalement Rasteroid — une implémentation propriétaire qui offrait les meilleures performances sur le matériel disponible.
Premier lancement réussi
Après les corrections sur l’Unicode, la mémoire et le wrapper OpenGL, Blender s’est finalement lancé sur le PDA/PocketPC.
Ce premier lancement, c’était quelque chose. L’interface était déformée, certains éléments mal placés, mais le programme tournait.

Finalisation du rendu visuel
Avec un Blender qui tournait mais s’affichait mal, il fallait corriger le rendu. J’avais essayé d’éviter d’apprendre OpenGL en profondeur. Mesa3d aurait pu être une solution, mais le convertir en virgule fixe pour les performances ARM aurait été un chantier monstrueux.
J’ai ouvert le Red Book (la référence OpenGL) et je me suis mis à lire, à comprendre et à implémenter…
Ce que j’ai découvert : OpenGL ES n’était pas si éloigné d’OpenGL ; il manquait principalement les mécanismes de sélection — le système utilisé par Blender pour détecter sur quel objet l’utilisateur clique. Une fois ces mécanismes réécrits proprement dans mon wrapper, Blender a retrouvé sa forme normale et parfaitement fonctionnelle.
Périmètre fonctionnel de BlenderPocket
La question revenait souvent : à quoi ça sert, concrètement ?
Voici la liste complète des fonctionnalités présentes dans BlenderPocket :
- Modélisation polygonale, courbes, metaballs, lattices
- UV Unwrapping
- Matériaux et textures
- Armatures et rigging
- Animation (courbes IPO, actions, NLA)
- Rendu classique, raytracing, radiosité
- Nodes (compositing et matériaux)
- Scripts Python (version optionnelle, +3 Mo)
- Image Editor




Ce qui a été exclu : le Game Engine, le son et la simulation physique. Ces fonctionnalités reposaient trop sur le calcul en virgule flottante ou sur des ressources absentes des PDA/PocketPC de l’époque.
Les véritables contraintes restaient la mémoire et l’absence de GPU. Tout était calculé par le microprocesseur. Les scènes devaient rester simples. Mais dans ces limites, tout ce qu’on aime dans Blender fonctionnait — et les fichiers .blend restaient parfaitement compatibles entre Windows, Mac, Linux et PDA/PocketPC. On pouvait commencer à modéliser dans les transports sur PDA et finir à la maison sur ordinateur sans aucune conversion.


Évolution vers les versions 2.4x
Il est important de préciser que l’ensemble de ce travail a été réalisé sur la base de l’architecture logicielle des versions 2.4x de Blender. Le portage initial était basé sur Blender 2.37a. Quand Blender 2.42 est sorti avec un système d’animation et de rendu entièrement refondu, j’ai tout resynchronisé facilement, ce qui fut un excellent test de la qualité d’organisation du code source.
Bilan honnête : les modifications apportées au code source original de Blender sont en réalité minimes. Je n’ai rien inventé avec BlenderPocket. J’ai simplement tiré parti du design architectural fantastique pensé par les développeurs originaux. L’essentiel du travail a consisté en de la configuration, de l’adaptation de l’environnement de compilation et du débogage. Beaucoup d’énergie et de code ont été produits pour arriver à un “diff” finalement assez court. C’est le prix à payer quand on apprend en faisant.
Un cadeau inattendu de cette synchronisation : les icônes de Blender 2.42 avaient été redessinées pour mieux s’adapter aux petits écrans. Je n’y suis pour rien. La Blender Foundation l’avait fait pour d’autres raisons, et cela tombait à pic pour BlenderPocket.


Bilan et retours d’expérience
Ce projet a exigé un investissement personnel conséquent. Il m’a poussé dans mes retranchements concernant la compréhension de la mémoire, de la compilation croisée et des pipelines graphiques. Techniquement, j’ai découvert l’architecture interne d’un projet C de grande envergure, les spécificités ARM, les subtilités d’OpenGL et les contraintes de cross-compilation pour WinCE. J’ai appris à écrire un wrapper de librairie graphique. Et j’ai même appris à lire du code commenté en néerlandais, ce qui ne me servira probablement plus jamais !
Mais ce qui m’a le plus marqué, c’est la réponse de la communauté open source. Ton Roosendaal prenant le temps de répondre à un inconnu avec un email détaillé et honnête. Daniel Wagner partageant son travail en toute confiance. La mailing list remettant en question mes mauvaises intuitions avant que je ne fasse de vrais dégâts.
Ce projet a pu exister parce que Blender avait été parfaitement conçu dès le début. Ma contribution a surtout consisté à croire que c’était faisable — et à m’y coller jusqu’au bout. Ma fascination pour ce logiciel, toujours à la pointe de la technologie aujourd’hui, n’en a été que renforcée.
Par la suite, l’aboutissement de ce travail a suscité un véritable intérêt au sein de la communauté, comme en témoignent les articles publiés sur Blendernation, dont celui-ci, qui ont mis en lumière mon portage auprès d’un plus large public. J’ai par ailleurs pu me rendre à la Blender Conference pour y présenter le projet, et j’ai même eu la chance incroyable de voir le grand Ton Roosendaal l’essayer en personne, comme on peut le voir sur ces photos :


Salvatore Russo