Initial Morph Target Weights

Yo @Deltakosh and @bghgary … How do i assign the initial morph target weights… In GLTF there is a and array for gltfMesh.weights… So if the guy is supposed to be smiling (WITHOUT ANIMATION) you can set blendShape - SmileLeft = 1 and SmileRight = 1…

When using Babylon Entities… I dont see anything to set the initial weights…

@bghgary … We had this problem in GLTF… You fixed it … How… So we can try implement in Babylon Entities as well ???

FYI… Here is how i export blend shaped now… Just dont see a WEIGHTS property

        private void ConvertUnityBlendShapesToBabylon(UnityEngine.Mesh mesh, SkinnedMeshRenderer skin, BabylonScene babylonScene, BabylonMesh babylonMesh)
            // Blend Shapes / Morph Targets
			if (mesh.blendShapeCount > 0)
                // Morph Target Manager
                var babylonMorphTargetManager = new BabylonMorphTargetManager();
                babylonMesh.morphTargetManagerId =;

                // Convert Morph Targets
                var babylonMorphTargets = new List<BabylonMorphTarget>();
				for (int blendShapeIndex = 0; blendShapeIndex < mesh.blendShapeCount; blendShapeIndex++)
					// As described above, a blend shape can have multiple frames.  Given that glTF only supports a single frame
					// per blend shape, we'll always use the final frame (the one that would be for when 100% weight is applied).
					string morphName = mesh.GetBlendShapeName(blendShapeIndex);
                    float morphWeight = skin.GetBlendShapeWeight(blendShapeIndex) / 100;
					int morphFrame = mesh.GetBlendShapeFrameCount(blendShapeIndex) - 1;

					var deltaVertices = new Vector3[mesh.vertexCount];
					var deltaNormals = new Vector3[mesh.vertexCount];
					var deltaTangents = new Vector3[mesh.vertexCount];
					mesh.GetBlendShapeFrameVertices(blendShapeIndex, morphFrame, deltaVertices, deltaNormals, deltaTangents);
                    // Blendshape
                    var babylonMorphTarget = new BabylonMorphTarget();
           = morphName;
                    // Influence
                    babylonMorphTarget.influence = 0f;
                    // Positions
                    babylonMorphTarget.positions = deltaVertices.ToFloat();
                    // Normals
                    babylonMorphTarget.normals = deltaNormals.ToFloat();
                    // Tangents
                    babylonMorphTarget.tangents = deltaTangents.ToFloat();
                    // Animations
                    /* TODO: Morph Animations
                    var animations = new List<BabylonAnimation>();
                    ExportFloatGameController(morphWeight, "influence", animations);
                    if (animations.Count > 0)
                        babylonMorphTarget.animations = animations.ToArray();

                babylonMorphTargetManager.targets = babylonMorphTargets.Count > 0 ? babylonMorphTargets.ToArray() : null;

The initial weights in babylon.js are supposed to be 0 (like no weight at all)

I’m ok if you want to add more info into the bjs loader

Yo @bghgary … Is there any conversions that is going on with the morph target positions.

In unity i serialize a Vector3[] containing morph target positions. I did a trace output of what those values are in Unity. The VERY FIRST position:

GLTF BlendShape: Blink_Left - Posiition:

But that very first position in babylon is showing as something TOTALLY different:

I have NO CLUE What is going on there.

Here is Screen shot from Unity Clearly showing Blink Left Position

But in babylon if i inspect the morph target positions:

Why are these number different… Is there some conversion or something that is going on GLTF for morph target positions or what ???

Yo @Deltakosh … What is the class VertexData used for… Am i supposed to be using that class for something in the entities export?

/// <summary>
   /// Store the data of the vertex used to extract the geometry.
   /// It used by the morph target in order to have the same vertex order between the mesh and the target.
   /// </summary>
   public class VertexData
       public int polygonId { get; set; }
       public int vertexIndexGlobal { get; set; }
       public int vertexIndexLocal { get; set; }

       public VertexData(int _polygonId, int _vertexIndexGlobal, int _vertexIndexLocal)
           polygonId = _polygonId;
           vertexIndexGlobal = _vertexIndexGlobal;
           vertexIndexLocal = _vertexIndexLocal;

They are used to store mapping info between morph targets. I used them while exporting morph info

Should I be using this class to export more targets from unity ???

If so, Have you got any examples using this class ???

Well this one is used by our 3dsmax exporter so this is probably the best place to look for an example

Yo @bghgary … Hey man do have any clue what going on here:

Unity stores blend shapes (morph targets) using a delta of the original. glTF does the same. Babylon, however, stores the absolute values of the shapes/targets. Is that perhaps what you are seeing?

Yo @bghgary

I think that it… How can i apply this delta ???

because i am trying to add morph targets to rgular babylon entities… so i am serializing these raw deltas WHICH IS WRONG… I should be calculating something with this delta right ???

Can you please show me that calculation ???

Where do you apply this delta to the original in GLTF Loader ???

It’s a delta (or displacement), just add the values to the original mesh values.

That seems to work… But the values are still different in babylon than when i serialize with GLTF… Why would that be ???

I’m not sure. What differences are you seeing?

Visually Nothing Different. But when i was tracing the value in babylon morph target manager targets… the first blend shape vertices.x value for Blink Left in GLTF = -0.1176459789276123

but with adding the delta to the mesh.vertices … the x = -0.2 something…

But they both look perfect… i have blend shape Smile_Left and Smile_Right set to 100

and this is BABYLON SCENE FILE (updating the delta positions in C# code):

        public static void UpdateBlendShapeDeltas(UnityEngine.Mesh mesh, Vector3[] deltaVertices, Vector3[] deltaNormals, Vector3[] deltaTangents)
            int index = 0;
            // Verticies
            if (mesh.vertices != null && mesh.vertices.Length == deltaVertices.Length)
                foreach (Vector3 vv in mesh.vertices)
                    deltaVertices[index] += vv;
            // Normals
            index = 0;
            if (mesh.normals != null && mesh.normals.Length == deltaNormals.Length)
                foreach (Vector3 nn in mesh.normals)
                    deltaNormals[index] += nn;
            // Tangents
            index = 0;
            if (mesh.tangents != null && mesh.tangents.Length == deltaTangents.Length)
                foreach (Vector4 tt in mesh.tangents)
                    deltaTangents[index] += new Vector3(tt.x, tt.y, tt.z);

Look slike this:

and the GLTF Version:

Look the exact same though… Which is good… Just seem weird that they would have different values

Anyways @bghgary It looks pretty good though … Thanks Again… You are always a BIG HELP :slight_smile:

1 Like

Hmm, can’t explain why there would be a difference. The code for adding the delta for the glTF loader is here: Babylon.js/glTFLoader.ts at master · BabylonJS/Babylon.js · GitHub

Me neither… I will double check GLTF Blend Shape Positions vs BABYLON Scene File Blend Shape Positions… But what ever the case, for some reason… its working in both like the screen shots above :slight_smile:

1 Like