Community
FBX Forum
Welcome to Autodesk’s FBX Forums. Share your knowledge, ask questions, and explore popular FBX topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Morph Target Normals

29 REPLIES 29
Reply
Message 1 of 30
kors.arioch
2171 Views, 29 Replies

Morph Target Normals

Hi again,

 

I have a problem in reading the normals info stored per Morph targets.

 

This is the code that I'm using, from the samples:

 

int lBlendShapeCount, lBlendShapeChannelCount, lTargetShapeCount;
FbxBlendShape* lBlendShape;
FbxBlendShapeChannel* lBlendShapeChannel;
FbxShape* lShape;

for (int lBlendShapeIndex = 0; lBlendShapeIndex < lBlendShapeCount; ++lBlendShapeIndex)
{
	lBlendShape = (FbxBlendShape*)pMesh->GetDeformer(lBlendShapeIndex, FbxDeformer::eBlendShape);
	lBlendShapeChannelCount = lBlendShape->GetBlendShapeChannelCount();
	for (int lBlendShapeChannelIndex = 0; lBlendShapeChannelIndex < lBlendShapeChannelCount; ++lBlendShapeChannelIndex)
	{
		lBlendShapeChannel = lBlendShape->GetBlendShapeChannel(lBlendShapeChannelIndex);
	
		lTargetShapeCount = lBlendShapeChannel->GetTargetShapeCount();
		for (int lTargetShapeIndex = 0; lTargetShapeIndex < lTargetShapeCount; ++lTargetShapeIndex)
		{
			lShape = lBlendShapeChannel->GetTargetShape(lTargetShapeIndex);


			int j, lControlPointsCount = lShape->GetControlPointsCount();
			FbxVector4* lControlPoints = lShape->GetControlPoints();
			FbxLayerElementArrayTemplate<FbxVector4>* lNormals = NULL;

bool lStatus = lShape->GetNormals(&lNormals);

[...]

The problem is:

lStatus always returns true, but the values are all 0.0!

 

I check the ASCII version of my FBX file and there are non 0 values in the propriety "normals" of each shape!

 

Where is my error?

 

29 REPLIES 29
Message 21 of 30
Numerator
in reply to: viviane.rochon

Message 22 of 30
Numerator
in reply to: kors.arioch

The FBX file is 90MB, so it might bounce if it was sent via email.  It will not upload to the forrm because it is too big.  Do you have another method for receiving files?

 

 

Message 23 of 30

I can send you by email the link for downloading it from my Google Drive. If that is ok.

Message 24 of 30

Hi Kors,

 

Could you figure out answer to your problem? Because I am stuck at the same error. It would be great help if you can help me with solution.

Message 25 of 30

Can someone post a simple repro case? The link for the test case does not
work.
Message 26 of 30
game16bit
in reply to: Numerator

I made a phenomenon that morph target Normals is wrong.
The first post different phenomenon, but I think the trouble.

 

 

model is 4 square simple.
Morph target has moved only one vertex, and turn the normal 90 degrees.

State is the normal line of the move vertices, which was fixed to the lock.

FBX is write in Ascii.
Seem to correctly value is in the field of looking at the contents [Normals].

 

Dump Then in ImportScene that the FBX in [FBX SDK \ 2016.1.1 \ samples \], re-calculated the normal is in the target.

 

The Export information and Import information is misaligned, than there is a problem with the SDK?

 

 

Message 27 of 30
par.winzell
in reply to: game16bit

Hey all. I've struggled with this the last few days, going through much the same steps as others have in this thread.

 

So the situation is that we've got an FbxBlendShape deformer; we've iterated over its FbxBlendShapeChannels, and we now have on our hands some number of actual FbxShape instances, where all the real data is kept.

 

We know we can easily get positional data from fbxShape->GetControlPoints(). That's defined in the FbxGeometryBase superclass. So is the function GetNormals() (although it's in the WARNING!! DO NOT USE! section, which should perhaps be a tip-off that we're in dangerous waters) which works fine for FbxMesh, but yields only zeroes for FbxShape.

 

And yeah, when you eyeball the file -- easiest with an ASCII export -- the normals are clearly there.

 

The access method that does seem to work is:

 

FbxGeometryElementNormal* shapeNormals = fbxShape->GetElementNormal();

which is more annoying to work with than GetNormals(), and requires checking shapeNormals->GetMappingMode() and shapeNormals->GetReferenceMode() and adjusting accordingly. The mapping mode will be eNone if there are no normals, or it can be eByControlPoint or ePolygonVertex and perhaps others. The reference mode can be either eDirect or eIndexToDirect. There's lots of examples of code around on how to deal with mapping mode and reference mode, but ultimately you're going to end up doing something like

fbxShape->GetElementNormal()->GetIndexArray()->GetAt(someIx)

and as far as I can tell, this does actually return us the normal we're looking for.

 

I'll be adding a (hopefully) working implementation of this to https://github.com/facebookincubator/FBX2glTF shortly, if anybody wants to see it in action.

 

Message 28 of 30
par.winzell
in reply to: par.winzell

One final wrinkle to all this:

  • I do get normals out of the method outlined above. They are pretty reasonable-seeming normals. However...
  • ... when I consult an ASCII save of the FBX file, I can see in plaintext what normal information is included in the file, and it's all zeroes!

The only conclusion that makes sense to me is that the FBX SDK actually computes normals (and maybe tangents) from the underlying geometry. While this is a nice service, it would be great if I had been told about it. There's a huge difference between author-originated normals and computed normals -- especially in the context of blend shapes.

 

I would still love any insight into whether Maya ever maintains normals for Blend Shapes, and/or whether they're lost in the export, and especially whether the FBX SDK computes them from geometry when they're requested using the method outlined in the previous post.

 

Message 29 of 30
regalir
in reply to: par.winzell

Hi,

 

the normals stored in the shapes (on disk) are ... deltas (the same way the vertices are) from the "base" geometry. This means that if you have a huge model but only one vertex has a displacement in the target shape, you will find only one value stored in the file. Upon reading the FBX file, the shape target is constructed by adding the deltas to the geometry base.

 

The correct method to access the normals on the shape, as par.winzell found out, is to go through the FbxShape:

 

FbxMesh* m = n->GetMesh();
int nbShapes = m->GetDeformerCount(FbxDeformer::eBlendShape);
for (int s = 0; s < nbShapes; s++)
{
	FbxBlendShape* lBS = FbxCast<FbxBlendShape>(m->GetDeformer(s, FbxDeformer::eBlendShape));
	if (lBS)
	{
		for (int bsc = 0, bscc = lBS->GetBlendShapeChannelCount(); bsc < bscc; bsc++)
		{
			FbxBlendShapeChannel* lBSC = lBS->GetBlendShapeChannel(bsc);
			for (int sc = 0, scc = lBSC->GetTargetShapeCount(); sc < scc; sc++)
			{
				FbxShape* lShape = lBSC->GetTargetShape(sc);
				for (int n = 0, nc = lShape->GetElementNormalCount(); n < nc; n++)
				{
					FbxLayerElementNormal* lN = (FbxLayerElementNormal*)lShape->GetElementNormal(n);
					// should check what is the mapping so we can access the data accordingly
					// if (lN->GetMappingMode() == FbxLayerElement::eByPolygonVertex) ...
					for (int i = 0; i < lN->GetDirectArray().GetCount(); i++)
					{
						FbxVector4 v = lN->GetDirectArray()[i];
						printf("%3d: %f %f %f\n", i, v[0], v[1], v[2]);
					}
				}
			}
		}
	}
}
Message 30 of 30
mrdeug08241
in reply to: regalir

I can use Facebook to send  it 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report