Get new vertices position using computeMorphedAttributes

Hello guys, I’m stuck in this issue while taking some experiments and I really need your help.

I have a 3D model with shape keys animations exported from Blender. Blue dots are control points that I manually select vertex index in Blender and create sphereMesh at that vertex position. (Deforming purpose)


When I update morphTargetInfluences, I remove the old ‘control points group’ and then onFinish I create new control points using new vertices position from morphedPositionAttribute.array that I receive after use the computeMorphedAttributes from BufferGeometryUtils

let morphChange = (type: number, value: number) => {
            removePoints(); // Remove old control points
            if(faceMesh.morphTargetInfluences){
                faceMesh.morphTargetInfluences[type] = value;
            }
        };
meshGUI.add(morphOptions, 'lowerLips', 0, 1, 0.01).onChange((value) => morphChange(1, value)).onFinishChange((finishvalue) => {
            let morphed: any = computeMorphedAttributes(faceMesh);
            faceMesh.geometry.setAttribute('position', morphed.morphedPositionAttribute);
            generatePoints(morphed);
});
let pointsArray = !morphedAttributes ? faceMesh.geometry.attributes.position.array : morphedAttributes.morphedPositionAttribute.array;
let itemSize = !morphedAttributes ? faceMesh.geometry.attributes.position.itemSize : morphedAttributes.morphedPositionAttribute.itemSize;

Everytime I update the value, the vertices (only vertices that morph takes effect) keep moving up, though I update the same value each time. The bigger value I update, the more distance vertices move up.



I’m not really understand what computeMorphedAttributes do. Please tell me more about 4 properties that I receive from computeMorphedAttributes : positionAttribute , normalAttribute , morphedPositionAttribute and morphedNormalAttribute .

P/s: Sorry for my bad english.

Someone help please.

My understanding is that you want to store the original attributes as a copy, do every modification starting with that unmodified copy, then apply them to the faceMesh. If you are reading the current state of the faceMesh, then updating it, it will slowly move up.

That or you just need to update morphTargetInfluences and not the positionAttribute. Use morphedPositionAttribute for the render. Can’t remember. Here’s some code that describes the behaviour.

const morphMesh = // your mesh with 2 influences, position and normal;

const meshPosAttrib = morphMesh.geometry.getAttribute('position');
const meshNormalAttrib = morphMesh.geometry.getAttribute('normal');

morphMesh.morphTargetInfluences[0] = 0.5;
morphMesh.morphTargetInfluences[1] = 0.5;

const computedAttributes = computeMorphedAttributes(morphMesh);

// these will be the same
expect(computedAttributes.positionAttribute).toStrictEqual(meshPosAttrib);
expect(computedAttributes.normalAttribute).toStrictEqual(meshNormalAttrib);

// these will change
expect(computedAttributes.morphedPositionAttribute).toBeDefined();
expect(computedAttributes.morphedNormalAttribute).toBeDefined();
1 Like

Thank you for replying my post. That’s really helpful suggestion. Let me try.

One more thing, because I read somewhere that morph is done GPU, not the CPU. So is it necessary to update the attributes of the faceMesh after I change the morph value? ( morphTargetInfluences)

1 Like

positionAttribute and normalAttribute are the original attributes of the mesh. Aren’t they?

computeMorphedAttributes is updating a buffer with values based on morphTargetInfluences. That is done in javascript so that is certainly done on the CPU.

Check the GLSL shaders to see if bone weights are passed to the renderer. I think they were last time I checked. That would be on the GPU.

If I remember correctly, the buffer values are calculated on the CPU and stored in the attribute for hit testing / querying for things like physics and picking. The weights are passed in an array or texture for rendering in the shader, shaders run on the GPU.

Don’t worry about how it gets to the GPU. The important part is that it looks correct and that your code has access to the data structure that describes the current state.

1 Like

Yes. Unless you updated them.

1 Like

I’ve tried. But it moved up right at the first time I morph the faceMesh.
As long as I add this: faceMesh.geometry.setAttribute('position', morphed.morphedPositionAttribute);
Seems like the morphTargetInfluences updated one more time.
I need my faceMesh have the new attributes so that my control points is at the right position.