Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There seem to be no way to access Blend Shapes values via code #15778

Open
Tracked by #63198
Rattel opened this issue Jan 16, 2018 · 11 comments
Open
Tracked by #63198

There seem to be no way to access Blend Shapes values via code #15778

Rattel opened this issue Jan 16, 2018 · 11 comments

Comments

@Rattel
Copy link

Rattel commented Jan 16, 2018

Godot version:
3.0 Beta 2

Issue description:
Looks like it's impossible to change values of a Blend Shape in a mesh with a script, or at least it's not documented, even though you can change them in the editor.

@ghost ghost added the documentation label Jan 17, 2018
@JosephCatrambone
Copy link
Contributor

JosephCatrambone commented Feb 19, 2018

After a lot of digging I see it's possible. If you have a mesh instance you need to call "set" on the mesh instance with "blend_shapes/". The capitalization has to match, but the spaces are removed. If you had "Face Smile" (as I did) then doing this should work:

onready var body = $Model/Skeleton/Body
var t = 0.0

func _process(delta):
	t += delta	
	if t > 1:
		t = 0
	body.set("blend_shapes/FaceSmile", t)

@bojidar-bg
Copy link
Contributor

Wouldn't it be better to change this issue to a "bug" or "enchancement", given it is quite unintuitive for users?
I guess it might be better to add a set_blend_amount(blendshape, amount) instead of documenting the workaround.

@JosephCatrambone
Copy link
Contributor

I'd agree. I spent a long time looking for how to do this and ended up digging through the code before finally stumbling upon a solution. A wrapper for the method wouldn't be unwelcome, especially if it caps the range to 0-1 as is needed by blendshapes.

@GeorgeS2019
Copy link

There is this method in VisualServer.cs

image

/// <summary>
/// <para>Sets the weight for a given blend shape associated with this instance.</para>
/// </summary>
[GodotMethod("instance_set_blend_shape_weight")]
public static void InstanceSetBlendShapeWeight(RID instance, int shape, float weight)
{
     NativeCalls.godot_icall_3_630(method_bind_262, ptr, RID.GetPtr(instance), shape, ref weight);
}

@lukostello
Copy link
Contributor

Just needs better documentation not different implementation IMO

@lukostello
Copy link
Contributor

I think I've actually changed my mind about this. Particularly because of how multimesh should handle blendshapes. If multimesh instances handled it the same way as mesh instances then that would mean that all meshes of the multimesh would have to have the same value of blendshape, where as if we instead were able to call a method you could use one of the parameters that make each mesh of the multimesh unique to make each blendshape have its own value. Which would be good if you had a bird mesh with flying blend shapes and you wanted them all to fly off at different times. In my case I want them all to have the same blend shape but the method would allow that flexibility. Having a method might even make the variables mesh instance has obsolete. I was going to make my own issue for blendshape support for multimeshes but this might solve that.

@clayjohn
Copy link
Member

@lukostello Using blendshapes with multimeshes is out of scope for this issue. This issue is about changing the values for a blend shape from script.

With respect to animating different multimesh instances differently with blendshapes, it is not trivial to implement and may not even be possible. MultiMeshes use GPU instancing which is different that having Mesh Instances in Godot. GPU instancing means that only one mesh is sent to the GPU and then it is rendered multiple times in a single draw call. What makes it fast is that only one mesh is used. Your suggestion would require the each instance uses a unique mesh (a blendshape is essentially another mesh) which would make it impossible to use GPU instancing. This problem is described well (from a tech artists persective) in the GDC talk "Creating the Art of ABZU" https://www.gdcvault.com/play/1024409/Creating-the-Art-of-ABZ. the speaker outlines their attempt to animate thousands of fish using blendshapes and how it was not possible, then they propose a solution, which is using vertex animation instead. Vertex animation works very well for simple Meshes (like fish or birds). The technique is also decribed in the Godot docs in the Animating thousands of fish with the MultiMeshInstance tutorial.

@lukostello
Copy link
Contributor

@clayjohn even in the instance where all meshes in the multimesh share the same blendshape?

@clayjohn
Copy link
Member

@lukostello It is technically possible for all instances to share a blend shape. However, the animations for all instances will be in synch. Further, I am not sure if Godot properly supports blend shapes with the MultiMeshInstance (from a quick glance it looks like it doesn't).

The way blendshapes work is that they process the mesh before it is drawn and actually morph the mesh stored on the GPU, so when it comes time to issue a draw call, the engine cant tell the difference between a mesh with blend shapes and a static mesh.

This is a problem for MultiMeshes because they only send one copy of the mesh to the GPU and then use GPU instancing to draw the same mesh multiple times.

@lukostello
Copy link
Contributor

@clayjohn that doesn't seem like a problem, just have the copy of the mesh being sent be the mesh made after the blend shapes are applied, but even if that does work that would mean all of them would be in sync which is what I want but its probably a pretty niche usage.

@clayjohn
Copy link
Member

that doesn't seem like a problem, just have the copy of the mesh being sent be the mesh made after the blend shapes are applied, but even if that does work that would mean all of them would be in sync which is what I want but its probably a pretty niche usage.

Feel free to open a proposal! I don't think it should be too much trouble to add. But of course, we would need to see if there is user demand before considering it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants