-
Notifications
You must be signed in to change notification settings - Fork 360
Description
Alternative title: Insomnia-fueled exploration of hxd.fmt.fbx
The problem
I came upon a bug with a specific FBX setup. Blockbench (a low-poly 3D modelling software) outputs an FBX model where LayerElementUV has MappingInformationType as ByPolygonVertex and ReferenceInformationType as Direct, which means there are no indices. Compare this to Blender's FBX format which outputs as ByPolygonVertex/IndexToDirect, with indices mapping polygons to UV coordinates.
The function hxd.fmt.fbx.Geometry.hx:getUVs considers the absence of indices as a Maya quirk and generates a list of indices with the exact same values as the geometry's PolygonVertexIndex, while it should, in our case, generate a list of continuous integers.
The current method:
public function getUVs() {
var uvs = [];
for( v in root.getAll("LayerElementUV") ) {
var index = v.get("UVIndex", true);
var values = v.get("UV").getFloats();
var index = if( index == null ) {
// ByVertice/Direct (Maya sometimes...)
[for( i in getPolygons() ) if( i < 0 ) -i - 1 else i];
} else index.getInts();
uvs.push({ values : values, index : index });
}
return uvs;
}My FBX's Geometry:
Vertices: *24 {
a: 400,800,400,400,800,-400,400,0,400,400,0,-400,-400,800,400,-400,800,-400,-400,0,400,-400,0,-400
}
PolygonVertexIndex: *24 {
a: 1,0,2,-4,6,4,5,-8,4,0,1,-6,3,2,6,-8,2,0,4,-7,5,1,3,-8
}
LayerElementUV: 0 {
Version: 101
Name: ""
MappingInformationType: "ByPolygonVertex"
ReferenceInformationType: "Direct"
UV: *48 {
a: 0.25,1,0,1,0,0.75,0.25,0.75,0.25,0.46875,0.25,0.71875,0,0.71875,0,0.46875,0.28125,0.75,0.53125,0.75,0.53125,1,0.28125,1,0.53125,0.46875,0.53125,0.71875,0.28125,0.71875,0.28125,0.46875,0.25,0.1875,0.25,0.4375,0,0.4375,0,0.1875,0.8125,1,0.5625,1,0.5625,0.75,0.8125,0.75
}
}
in a nutshell
- 8 vertices (24 values)
- 6 quads (24 values)
- 24 UV coordinates (48 values)
Expected output of "index" in getUVs' return output:
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]: length 24
Where 6 quads are represented in 24 UV coordinates.
(each four UV indices represent a quad)
Current output:
[for( i in getPolygons() ) if( i < 0 ) -i - 1 else i];
or
[1,0,2,3,6,4,5,7,4,0,1,5,3,2,6,7,2,0,4,6,5,1,3,-8] length 24
Which is the same value as PolygonVertexIndex, 1,0,2,-4,6,4,5,-8,4,0,1,-6,3,2,6,-8,2,0,4,-7,5,1,3,-8.
A possible solution
Here's an edited getUVs that would still support Maya and also support ByPolygonVertex/Direct. A cleaner approach would be to use enums, but it's important to note that for the FBX format both ByVertex and ByVertice are valid keywords.
public function getUVs() {
var uvs = [];
var mapping_type = root.get("LayerElementUV.MappingInformationType").props[0].toString();
for( v in root.getAll("LayerElementUV") ) {
var index = v.get("UVIndex", true);
var values = v.get("UV").getFloats();
var indices = null;
// Ref info type is Direct instead of IndexToDirect
if (index == null)
{
if (mapping_type == "ByVertex" || mapping_type == "ByVertice")
{
// Original Maya approach
indices = [for( i in getPolygons() ) if( i < 0 ) -i - 1 else i];
}
else if (mapping_type == "ByPolygonVertex")
{
// Blockbench approach
indices = [for(i in 0...getPolygons().length) i];
}
}
else {
indices = index.getInts();
}
uvs.push({ values : values, index : indices });
}
return uvs;
}Note that I could not test a Maya FBX, but the code for it should not have changed.