Le but de ce projet est de réaliser une application qui permet de se serrer la main virtuellement, tout en étant très loin.
Pour cela nous utiliserons 2 Leap Motions connectés grâce à un serveur. Nous voulons que notre programme tourne sur le plus possible de platformes et soit testable facilement, nous coderons donc en javascript. Le serveur sera réalisé avec NodeJS.
Le serveur pourra accueillir de nombreux clients, les clients possédant un leap motion (l'api détecte un leap motion allumé) seront des acteurs, les autres seront des spectateurs.
Une amélioration possibles de ce programme sera de rajouter des objets avec lesquels l'utilisateur pourra interagir.
Comme dans la plupart de mes projets WebGL, je part d'une structure de base, que j'ai développée et que j'améliore au fil des projets. Celle-ci comprend principalement un fichier Engine.js qui rassemble toutes les classes utiles à la 3D et un fichier index.js qui contiens l'application. Pour des questions de performances, je n'utilise pas le framework Three.js, donc je dois recoder pas mal de fonctions de base.
Afin d'avoir une main qui ressemble à quelque-chose, je vais dessiner la main sous blender, puis l'exporter au format obj. Mais comment faire pour assigner un groupe de vertices (points) à une phalange ? En effet, il n'existe aucun format standard de description de “squelette d'animation”. La motion capture, les jeux vidéos et les moteurs de jeux open-sources utilisent chacun leur propre systèmes qui sont souvent trop verbeux donc difficiles à parser en javascript. Il y a quelques années, j'ai développé un format léger qui permet cela, pour le moteur de jeu Spout (minecraft open-source). Sur leur dépôt github, on peut télécharger le plugin Blender que j'avais codé, qui permet d'exporter au format .ske :
import bpy; from bpy_extras.io_utils import ExportHelper; bl_info = { "name": "Spout Skeleton", "author": "Karang", "blender": (2,6,2), "version": (0,0,1), "location": "File > Import-Export", "description": "Export skeleton for spout engine.", "category": "Import-Export" } class ExportSKE(bpy.types.Operator, ExportHelper): bl_idname = "export_bones.ske"; bl_label = "Spout Animation Model"; bl_options = {'PRESET'}; filename_ext = ".ske"; def saveSKE(self, context, path): f = open(path, "w", encoding="utf8", newline="\n"); obj = context.object; armature = obj.parent.data; vgroups = {}; for group in obj.vertex_groups: vgroups[group.name] = []; for v in obj.data.vertices: for group in v.groups: vgroups[obj.vertex_groups[group.group].name].append(v.index); children = {None: []}; for bone in armature.bones: children[bone.name] = []; for bone in armature.bones: children[getattr(bone.parent, "name", None)].append(bone.name); def writeBones(bone, indent): indent_str = (indent*4) * " "; f.write(indent_str + bone + ":\n"); indent_str += " "; # Children if (children[bone]): f.write(indent_str + "children:\n"); for child in children[bone]: writeBones(child, indent+2); # Vertices & Weight if (vgroups[bone]): f.write(indent_str + "vertices:"); for v in vgroups[bone]: f.write(" " + str(v)); f.write("\n"); f.write(indent_str + "weight:"); for v in vgroups[bone]: f.write(" %.4f" % obj.vertex_groups[bone].weight(v)); f.write("\n"); writeBones(children[None][0], 0); f.close(); return {'FINISHED'}; def execute(self, context): path = self.as_keywords()["filepath"]; return self.saveSKE(context, path); def menu_func(self, context): self.layout.operator(ExportSKE.bl_idname, text="Spout Skeleton (.ske)"); def register(): bpy.utils.register_module(__name__); bpy.types.INFO_MT_file_export.append(menu_func); def unregister(): bpy.utils.unregister_module(__name__); bpy.types.INFO_MT_file_export.remove(menu_func); if __name__ == "__main__": register()
Le guide du sdk leap motion nous done la représentation d'une main tel que donnée par l'appareil.
Nous pouvons donc modéliser n'importe quel type de main (robot, humain, ET, …) tant qu'elle respecte l'anatomie d'une main humaine.
Le code de ce projet est open-source, vous pouvez le trouver sur cloud9.
A suivre …