Skip to content

Commit bc113cb

Browse files
committed
if there are duplicate vertices then merge them in the fbx file
- get the vertices that we need, as well as their index in the new triangle array. - export normals by polygon vertex instead of control point, as one control point may have multiple normals.
1 parent 5da711d commit bc113cb

File tree

1 file changed

+42
-29
lines changed

1 file changed

+42
-29
lines changed

Assets/FbxExporters/Editor/FbxExporter.cs

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class ModelExporter : System.IDisposable
5454
/// <summary>
5555
/// Export the mesh's UVs using layer 0.
5656
/// </summary>
57-
public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriangles)
57+
public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] unmergedTriangles)
5858
{
5959
// Set the normals on Layer 0.
6060
FbxLayer fbxLayer = fbxMesh.GetLayer (0 /* default layer */);
@@ -65,22 +65,20 @@ public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriang
6565

6666
using (var fbxLayerElement = FbxLayerElementNormal.Create (fbxMesh, "Normals"))
6767
{
68-
fbxLayerElement.SetMappingMode (FbxLayerElement.EMappingMode.eByControlPoint);
69-
70-
// TODO: normals for each triangle vertex instead of averaged per control point
71-
//fbxNormalLayer.SetMappingMode (FbxLayerElement.eByPolygonVertex);
68+
fbxLayerElement.SetMappingMode (FbxLayerElement.EMappingMode.eByPolygonVertex);
7269

7370
fbxLayerElement.SetReferenceMode (FbxLayerElement.EReferenceMode.eDirect);
7471

7572
// Add one normal per each vertex face index (3 per triangle)
7673
FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray ();
7774

78-
for (int n = 0; n < mesh.Normals.Length; n++)
79-
{
80-
fbxElementArray.Add (new FbxVector4 (-mesh.Normals [n] [0],
81-
mesh.Normals [n] [1],
82-
mesh.Normals [n] [2]));
83-
}
75+
for (int n = 0; n < unmergedTriangles.Length; n++) {
76+
int unityTriangle = unmergedTriangles [n];
77+
fbxElementArray.Add (new FbxVector4 (-mesh.Normals [unityTriangle] [0],
78+
mesh.Normals [unityTriangle] [1],
79+
mesh.Normals [unityTriangle] [2]));
80+
}
81+
8482
fbxLayer.SetNormals (fbxLayerElement);
8583
}
8684

@@ -92,20 +90,19 @@ public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriang
9290
// set texture coordinates per vertex
9391
FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray ();
9492

93+
// TODO: only copy unique UVs into this array, and index appropriately
9594
for (int n = 0; n < mesh.UV.Length; n++) {
9695
fbxElementArray.Add (new FbxVector2 (mesh.UV [n] [0],
9796
mesh.UV [n] [1]));
9897
}
9998

10099
// For each face index, point to a texture uv
101-
var unityTriangles = mesh.Triangles;
102100
FbxLayerElementArray fbxIndexArray = fbxLayerElement.GetIndexArray ();
103-
fbxIndexArray.SetCount (unityTriangles.Length);
101+
fbxIndexArray.SetCount (unmergedTriangles.Length);
104102

105-
for(int i = 0; i < fbxTriangles.Length; i++){
106-
fbxIndexArray.SetAt (i, fbxTriangles [i]);
103+
for(int i = 0; i < unmergedTriangles.Length; i++){
104+
fbxIndexArray.SetAt (i, unmergedTriangles [i]);
107105
}
108-
109106
fbxLayer.SetUVs (fbxLayerElement, FbxLayerElement.EType.eTextureDiffuse);
110107
}
111108
}
@@ -215,50 +212,66 @@ public void ExportMesh (MeshInfo meshInfo, FbxNode fbxNode, FbxScene fbxScene)
215212

216213
NumMeshes++;
217214
NumTriangles += meshInfo.Triangles.Length / 3;
218-
NumVertices += meshInfo.VertexCount;
219215

220216
// create the mesh structure.
221217
FbxMesh fbxMesh = FbxMesh.Create (fbxScene, "Scene");
222218

223219
// Create control points.
224-
int NumControlPoints = meshInfo.VertexCount;
220+
Dictionary<Vector3, int> ControlPointToIndex = new Dictionary<Vector3, int> ();
221+
222+
int NumControlPoints = 0;
223+
for (int v = 0; v < meshInfo.VertexCount; v++) {
224+
if (ControlPointToIndex.ContainsKey (meshInfo.Vertices [v])) {
225+
continue;
226+
}
227+
ControlPointToIndex [meshInfo.Vertices [v]] = NumControlPoints;
228+
229+
NumControlPoints++;
230+
}
231+
232+
NumVertices += NumControlPoints;
225233

226234
fbxMesh.InitControlPoints (NumControlPoints);
227235

228236
// copy control point data from Unity to FBX
229-
for (int v = 0; v < meshInfo.VertexCount; v++)
230-
{
237+
foreach (var controlPoint in ControlPointToIndex.Keys) {
231238
fbxMesh.SetControlPointAt(new FbxVector4 (
232-
-meshInfo.Vertices [v].x,
233-
meshInfo.Vertices [v].y,
234-
meshInfo.Vertices [v].z
235-
), v);
239+
-controlPoint.x,
240+
controlPoint.y,
241+
controlPoint.z
242+
), ControlPointToIndex[controlPoint]);
236243
}
237244

238245
/*
239246
* Triangles have to be added in reverse order,
240247
* or else they will be inverted on import
241248
* (due to the conversion from left to right handed coords)
242249
*/
243-
int[] fbxTriangles = new int[meshInfo.Triangles.Length];
250+
int[] unmergedTriangles = new int[meshInfo.Triangles.Length];
244251
int current = 0;
245252
for (int f = 0; f < meshInfo.Triangles.Length / 3; f++)
246253
{
247254
fbxMesh.BeginPolygon ();
248255

256+
// triangle vertices have to be reordered to be 0,2,1 instead
257+
// of 0,1,2, as this gets flipped back during import
249258
foreach (int val in new int[]{0,2,1}) {
250259
int tri = meshInfo.Triangles [3 * f + val];
260+
261+
// Save the triangle order (without merging vertices) so we
262+
// properly export UVs, normals, binormals, etc.
263+
unmergedTriangles [current] = tri;
264+
265+
int index = ControlPointToIndex [meshInfo.Vertices [tri]];
266+
tri = index;
251267
fbxMesh.AddPolygon (tri);
252268

253-
// save the exported triangle order so we
254-
// properly export UVs
255-
fbxTriangles [current] = tri;
256269
current++;
257270
}
258271
fbxMesh.EndPolygon ();
259272
}
260273

261-
ExportUVsAndNormals (meshInfo, fbxMesh, fbxTriangles);
274+
ExportUVsAndNormals (meshInfo, fbxMesh, unmergedTriangles);
262275

263276
var fbxMaterial = ExportMaterial (meshInfo.Material, fbxScene);
264277
fbxNode.AddMaterial (fbxMaterial);

0 commit comments

Comments
 (0)