cyrillef / FBX-glTF

FBX glTF importer/exporter plug-in and converter.
MIT License
211 stars 50 forks source link

Wrong indexing used for normals, etc. in gltfwriterVBO::GetLayerElements #15

Open alinen opened 7 years ago

alinen commented 7 years ago

The resulting glTF has incorrect normals as a result.

To work around the issue, I have changed the macro GetLayerElement to use the MappingMode rather than the ReferenceMode, like so

define GetLayerElement(layerElt, indexV, T, V, index, lambda) \

int indexV =-1 ; \
T V ; \
if ( layerElt ) { \
    indexV =(layerElt->GetMappingMode () == FbxLayerElement::eByPolygonVertex ? index : layerElt->GetIndexArray () [index]) ; \
    V =layerElt->GetDirectArray ().GetAt (indexV) ; \
    lambda (V) ; \
}

Models that demonstrate the problem are here

https://github.com/alinen/FBX-glTF/tree/master/three.js/models/drone_shell (needs updated three.js too) https://github.com/alinen/FBX-glTF/tree/master/three.js/models/airplane

I would be interested in knowing the proper fix!

alinen commented 7 years ago

Some more info: Changing the FBX export options broke my fix above. I am now sending the vertexID to the macro like so

GetLayerElement (pLayerElementNormals, normalIndex, FbxVector4, normal, index, vertexID, [this] (FbxVector4 &V) { _in_normals.push_back (V) ; }) ;

And then using the following modified macro

define GetLayerElement(layerElt, indexV, T, V, index, vIndex, lambda) \

int indexV =-1 ; \
T V ; \
if ( layerElt ) { \
    if (layerElt->GetMappingMode() == FbxLayerElement:: eByControlPoint ) indexV = vIndex; \
    else indexV =(layerElt->GetReferenceMode () == FbxLayerElement::eDirect ? index : layerElt->GetIndexArray () [index]) ; \
    V =layerElt->GetDirectArray ().GetAt (indexV) ; \
    lambda (V) ; \
}

And the FBX you would need for testing are here

https://github.com/alinen/FBX-glTF/models/airplane/airplane.fbx https://github.com/alinen/FBX-glTF/models/drone/DRONE_Shell.fbx

Again, advice would be appreciated!