Banque de cours - Transfert de shape keys de Vertex vers Shape Blends (format mdd)
5 min de lecture
Transfert de shape keys de Vertex vers Shape Blends (format mdd)
Une technique pour exporter une animation geo nodes ou par modifiers (e.g. Ocean ou Wave Modifier) de Blender vers Unity,
Cette technique fonctionne bien lorsqu’il s’agit, un peu comme les VAT (Vertex Animation Texture), de modifier les vecteurs des vertices sans en ajouter ou en retirer.
⚠️
Il est important de choisir un frame rate adéquat. On va choisir, ici, 60 fps (dans les paramètres Output).
Créer un Plane et ajoutez un Ocean Modifier.
Dans les paramètres Waves, mettre l’échelle à 2.5 et le “Choppiness” à 2 pour avoir des vagues plus hautes et plus cassées.
Pour que que le Blend Shape fonctionne dans Unity, il faut une animation avec des keyframes.
Keyframer le time à 0 au Frame 1, puis à 10 par exemple, au frame 250.
Assurez-vous que l’interpolation est linéaire et qu’il n’y a pas de Ease-In ou Ease-Out (Sélectionner tous les keyframes, ou tout les points dans le graph editor, cliquer-droit et choisir Interpolation Mode → Linear et Easing Type → Automatic Easing).
Installer et activer l’add-on “NewTek MDD format” et l’activer.
Le format NewTek MDD (Motion Designer Data) est un format de fichier d’animation basé sur l’utilisation de shape keys utilisé qui permet de stocker les données de déplacement de vertex dans une animation 3D. Il a été développé à l’origine pour LightWave 3D, un logiciel de modélisation et d’animation de NewTek, mais il est aussi utilisé dans d’autres logiciels 3D comme Blender, Maya (via des plugins), Houdini, etc.
Le fichier .mdd contient les positions de tous les sommets d’un objet 3D à chaque frame de l’animation. (Ça ressemble au textures VAT hein!). Cela permet de :
Transférer des animations précises (notamment des simulations complexes comme des cloths, fluides ou destructions) entre différents logiciels.
Jouer une animation en “bake”, c’est-à-dire sans avoir besoin des armatures, simulations ou contraintes d’origine.
Faciliter le rendu dans des moteurs externes ou pipelines complexes.
Structure typique d’un fichier .mdd :
Nombre de points (sommets)
Nombre de frames
Pour chaque frame : une liste de positions (x, y, z) pour chaque sommet
Sélectionner le Plane et faire File → Export → “Lightwave Point Cache (.mdd)”. Ce sous-menu a été ajouté par l’add-on qu’on vient d’activer.
Appliquer le modifier. L’animation va disparaître, mais elle est, maintenant, frame par frame et vertex par vertex, dans le fichier .mdd.
Sélectionner encore une fois l’objet inanimé et sans modifiers et faire “File → Import → “Lightwave Point Cache (.mdd)” et choisir le fichier qu’on a exporté durant l’opération d’export.
Faites Play, l’objet est à nouveau animé, mais cette fois-ci avec des keyframes pour chaque frame et pour chaque Vertex!
Maintenant, il vous suffit d’exporter l’objet en format FBX. Ne pas oublier d’activer “Limnit to: Selected Objects” et d’activer le checkbox “Animation”.
Ok, on passe à Unity.
Unity est capable de comprendre les shape keys (qu’il appelle Blend Shapes) mais il faut écrire un script pour looper à travers tous les blend shapes. Le script est inspiré de ceci, qu’on peut trouver dans la doc de Unity 6:
Dans Unity, drag and drop le FBX dans les assets puis dans la scène.
Créer un nouveau script (+ en dessous de Project, “Monobehaviour script”) et le nommer ShapeBend.cs
Drag and drop le FBX dans la scène (sous Hierarchy)
Associer à cet objet le script suivant (appelez-le “ShapeBend.cs” par exemple) que vous aurez écrit. La bonne nouvelle, c’est que c’est le même script pour n’importe quel animation généré par cette méthode.
using System.Collections;using System.Collections.Generic;using UnityEngine;public class NewMonoBehaviourScript : MonoBehaviour{ SkinnedMeshRenderer skinnedMeshRenderer; Mesh skinnedMesh; int blendShapeCount; int playIndex = 0; // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>(); skinnedMesh = GetComponent<SkinnedMeshRenderer>().sharedMesh; blendShapeCount = skinnedMesh.blendShapeCount; } // Update is called once per frame void Update() { if (playIndex > 0) skinnedMeshRenderer.SetBlendShapeWeight(playIndex - 1, 0f); if (playIndex == 0) skinnedMeshRenderer.SetBlendShapeWeight(blendShapeCount - 1, 0f); skinnedMeshRenderer.SetBlendShapeWeight(playIndex, 100f); playIndex++; if (playIndex > blendShapeCount - 1) playIndex = 0; }}
Ajouter un Empty à la scène et lui associer le code suivant (Appelez-le ”FpsLock.cs” par exemple). Ce code impose le même frame rate que celui utilisé dans Blender (donc modifier la valeur en fonction de votre animation Blender).
Si vous ne le faites pas, l’animation va tourner trop vite.
🔥
Ceci est un quickfix. Idéalement, on impose pas de frame rate, mais on contrôle la durée de l’animation.
using System.Collections;using System.Collections.Generic;using UnityEngine;public class FpsLock : MonoBehaviour{ // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { Application.targetFrameRate = 30; } // Update is called once per frame void Update() { }}
Jouez la scène. Badabeen, badaboon! (Ajouter un component “Free Camera” à l’objet “Main Camera” si vous voulez vous promener dedans en mode “Play”).
Key stuff:
Limitation: la géométrie doit être la même en termes de nombre de vertex. Si l’animation dans Blender on ajoute ou en enlève, cette méthode ne fonctionnera pas.
Ça fonctionne donc avec, par exemple, Wave Modifier, Lattice Modifier, cloth simulation, etc.
Pour le geo nodes, ça ne fonctionne pas si les geo nodes ajoutent de la géométrie par rapport à l’objet de base. Et pourtant…
FpsLock C# file associated with an empty in the scene, frame rate should be the same as the one set in Blender
Enable mdd add-on in Blender
Une manière brillante de rendre votre loop “seamless”: