[SOLVED] 2.9 Morphing not working (morph targets / blend shapes)


photo

Recommended Posts

Hi,

I observed in 2.9 that morph targets not works. The shape is not changing.

I attach you a file to figure it out. 

void MorphTest::init()
{
	mesh = ObjectMeshSkinned::cast(Editor::get()->getNodeByName("pCube2"));
	mesh->setNumTargets(2, 0);
}

void MorphTest::update()
{
	float time = Game::get()->getTime() * 2.0f;

	float k0 = sin(time * 3.0f) + 0.75f;
	float k1 = cos(time * 3.0f) + 0.75f;

	mesh->setTarget(0, 1, 0, k0, 0);
	mesh->setTarget(1, 1, 0, k1, 0);

	
}

edit:

- In Deformed Models tab I checked Deformed Models and Blend Shapes (in export options)
- Also I checked Input Connections in Connections tab (in export options)
- In Unigine I selected Import Morph Targets (in import options)

- As well I verified such exporeted file in other 3D software/engine where morphs works - the file is correct and Morphing works (except Unigine)
- I attach fbx file where is just one morph shape added to base shape (it's just change the position of vertices for one edge of the box)

blend_selection_bin_ic.fbx

Edited by Klimczak.Jan
Additional information
Link to post

Hello @morbid,

that's strength behaviour, it's scale my object instead blending it (I have the same issue). The valid shapes are (from .fbx file):

image.png.68395dfd5d75001e83c61bc00eb8f654.png

morphing should morph box to triangle based box withoud changing it's size.

Link to post

Hi Jan,

We've found a mistake in your code. For correct behavior you should compensate each target with negative coefficient, like here:

void MorphTest::init()
{
	mesh = ObjectMeshSkinned::cast(Editor::get()->getNodeByName("pCube2"));
	mesh->setNumTargets(3, 0);
}

void MorphTest::update()
{
	float time = Game::get()->getTime() * 2.0f;

	float k0 = sin(time * 3.0f) * 0.5f + 0.5f;

	mesh->setTarget(0, 1, 0, 1.0f, 0);
	mesh->setTarget(1, 1, 0, -k0, 0);
	mesh->setTarget(2, 1, 0, k0, 0);

	
}

Check our article and samples on morph targets, this approach with negative coefficient is used in every case:

https://developer.unigine.com/en/docs/2.9/content/tutorials/morph/

Thanks!

  • Like 1

How to submit a good bug report
---
FTP server for test scenes and user uploads:

Link to post

Hi @morbid,

Do you try it with the file which I attach to the post? Unfortunatelly it not working for me even with negative coeficient. For my, only provided by unigine samples works correct (but I cant analize it becasuse they are not the fbx files).

Also I have a little problem to understand how internally morphing works in unigine sdk? If I have one mesh with just one blend target then why I have to setup 3 target for it?  And why I have to use negative coeficient? I think that such knowledge will help me to work with that.

Thanks 

Link to post

Hello @Klimczak.Jan,

We are sorry about the typo we made in the snippet above, it should be as follows:

void MorphTest::init()
{
	mesh = ObjectMeshSkinned::cast(Editor::get()->getNodeByName("pCube2"));
	mesh->setNumTargets(3, 0);
}

void MorphTest::update()
{
	float time = Game::get()->getTime() * 2.0f;
	float k0 = sin(time * 3.0f) * 0.5f + 0.5f;

	mesh->setTarget(0, 1, 0, 1.0f, 0);
	mesh->setTarget(1, 1, 0, -k0, 0);
	mesh->setTarget(2, 1, 1, k0, 0); // here the target index must be 1
}

As it is told in the Adding Morph Targets article, all enabled targets are multiplied by their weights and added up according to the formula:

final_xyz = target_0_xyz * weight_0 + target_1_xyz * weight_1 + ...

Using a negative compensatory coefficient is just a handy workaround preventing the model from inflating (since the final position of each point is the sum of the target ones), it's pretty useful when using multiple targets. You can blend two shapes in a more natural way:

void MorphTest::init()
{
	mesh = ObjectMeshSkinned::cast(Editor::get()->getNodeByName("pCube2"));
	mesh->setNumTargets(2, 0);
}

void MorphTest::update()
{
	float time = Game::get()->getTime() * 2.0f;
	float k0 = sin(time * 3.0f) * 0.5f + 0.5f;

	mesh->setTarget(0, 1, 0, k0, 0);
	mesh->setTarget(1, 1, 1, 1 - k0, 0); // we just subtract the weight of the first target from the maximum
}

 

You can set up as many morph targets as you need, but each target should be associated with one of blend shapes from the model. Check this out:

void MorphTest::init()
{
	mesh = ObjectMeshSkinned::cast(Editor::get()->getNodeByName("pCube2"));
	mesh->setNumTargets(mesh->getNumSurfaceTargets(0) + 1, 0); // set up as many targets as the 0 surface has plus 1
  
    // enable each target and associate it with the corresponding blend shape
	mesh->setTargetEnabled(0, 1, 0); // straight box
	mesh->setTargetIndex(0, 0, 0); 
  
	mesh->setTargetEnabled(1, 1, 0); // an auxiliary compensatory target
	mesh->setTargetIndex(1, 0, 0);
  
	mesh->setTargetEnabled(2, 1, 0); // skewed box
	mesh->setTargetIndex(2, 1, 0);
}

void MorphTest::update()
{
	float time = Game::get()->getTime() * 2.0f;
	float k0 = sin(time * 3.0f) * 0.5f + 0.5f;

	mesh->setTargetWeight(0, 1.0f, 0); // and then simply adjust the weights
	mesh->setTargetWeight(1, -k0, 0); // using a negative weight here is the same as setting 1-k0 value
 	mesh->setTargetWeight(1, k0, 0);
}

So the setTarget function just gathers all target parameters together for convenience.

All the samples above were checked with your fbx in 2.9 SDK.

morphing.gif

Hope this helps!

Thank you.

  • Like 2
Link to post

Hello @thomalex and @morbid,

Thank you for very good and detailed explaination and for solve my problem. Now everyhing work as expecten and I understand why it is working like that. I thing such additional examples you could add to documentation. It explain why to use negative coeficient, which is a good idea to use :)

Thank You

Link to post
  • morbid changed the title to [SOLVED] 2.9 Morphing not working (morph targets / blend shapes)