Skip to content

Commit 3490254

Browse files
authored
Merge pull request #7 from Unity-Technologies/UNI-20504-merge-duplicate-verts-on-export
Uni 20504 merge duplicate verts on export
2 parents 418ebac + 17ac800 commit 3490254

File tree

1 file changed

+59
-38
lines changed

1 file changed

+59
-38
lines changed

Assets/FbxExporters/Editor/FbxExporter.cs

Lines changed: 59 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public static ModelExporter Create ()
5757
/// <summary>
5858
/// Export the mesh's UVs using layer 0.
5959
/// </summary>
60-
public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriangles)
60+
public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] unmergedTriangles)
6161
{
6262
// Set the normals on Layer 0.
6363
FbxLayer fbxLayer = fbxMesh.GetLayer (0 /* default layer */);
@@ -67,23 +67,22 @@ public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriang
6767
}
6868

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

7572
fbxLayerElement.SetReferenceMode (FbxLayerElement.EReferenceMode.eDirect);
7673

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

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

8887
using (var fbxLayerElement = FbxLayerElementUV.Create (fbxMesh, "UVSet")) {
8988
fbxLayerElement.SetMappingMode (FbxLayerElement.EMappingMode.eByPolygonVertex);
@@ -92,20 +91,19 @@ public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriang
9291
// set texture coordinates per vertex
9392
FbxLayerElementArray fbxElementArray = fbxLayerElement.GetDirectArray ();
9493

94+
// TODO: only copy unique UVs into this array, and index appropriately
9595
for (int n = 0; n < mesh.UV.Length; n++) {
9696
fbxElementArray.Add (new FbxVector2 (mesh.UV [n] [0],
9797
mesh.UV [n] [1]));
9898
}
9999

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

105-
for (int i = 0; i < fbxTriangles.Length; i++) {
106-
fbxIndexArray.SetAt (i, fbxTriangles [i]);
104+
for(int i = 0; i < unmergedTriangles.Length; i++){
105+
fbxIndexArray.SetAt (i, unmergedTriangles [i]);
107106
}
108-
109107
fbxLayer.SetUVs (fbxLayerElement, FbxLayerElement.EType.eTextureDiffuse);
110108
}
111109
}
@@ -223,31 +221,54 @@ public FbxSurfaceMaterial ExportMaterial (Material unityMaterial, FbxScene fbxSc
223221
/// Unconditionally export this mesh object to the file.
224222
/// We have decided; this mesh is definitely getting exported.
225223
/// </summary>
226-
public void ExportMesh (MeshInfo meshInfo, FbxNode fbxNode, FbxScene fbxScene)
224+
public void ExportMesh (MeshInfo meshInfo, FbxNode fbxNode, FbxScene fbxScene, bool weldVertices = true)
227225
{
228226
if (!meshInfo.IsValid)
229227
return;
230228

231229
NumMeshes++;
232230
NumTriangles += meshInfo.Triangles.Length / 3;
233-
NumVertices += meshInfo.VertexCount;
234231

235232
// create the mesh structure.
236233
FbxMesh fbxMesh = FbxMesh.Create (fbxScene, "Scene");
237234

238235
// Create control points.
239-
int NumControlPoints = meshInfo.VertexCount;
236+
Dictionary<Vector3, int> ControlPointToIndex = new Dictionary<Vector3, int> ();
240237

241-
fbxMesh.InitControlPoints (NumControlPoints);
238+
int NumControlPoints = 0;
239+
if (weldVertices) {
240+
for (int v = 0; v < meshInfo.VertexCount; v++) {
241+
if (ControlPointToIndex.ContainsKey (meshInfo.Vertices [v])) {
242+
continue;
243+
}
244+
ControlPointToIndex [meshInfo.Vertices [v]] = NumControlPoints;
242245

243-
// copy control point data from Unity to FBX
244-
for (int v = 0; v < meshInfo.VertexCount; v++) {
245-
// convert from left to right-handed by negating x (Unity negates x again on import)
246-
fbxMesh.SetControlPointAt (new FbxVector4 (
247-
-meshInfo.Vertices [v].x,
248-
meshInfo.Vertices [v].y,
249-
meshInfo.Vertices [v].z
250-
), v);
246+
NumControlPoints++;
247+
}
248+
fbxMesh.InitControlPoints (NumControlPoints);
249+
250+
// copy control point data from Unity to FBX
251+
foreach (var controlPoint in ControlPointToIndex.Keys) {
252+
fbxMesh.SetControlPointAt (new FbxVector4 (
253+
-controlPoint.x,
254+
controlPoint.y,
255+
controlPoint.z
256+
), ControlPointToIndex [controlPoint]);
257+
}
258+
} else {
259+
NumControlPoints = meshInfo.VertexCount;
260+
fbxMesh.InitControlPoints (NumControlPoints);
261+
262+
// copy control point data from Unity to FBX
263+
for (int v = 0; v < NumControlPoints; v++)
264+
{
265+
// convert from left to right-handed by negating x (Unity negates x again on import)
266+
fbxMesh.SetControlPointAt(new FbxVector4 (
267+
-meshInfo.Vertices [v].x,
268+
meshInfo.Vertices [v].y,
269+
meshInfo.Vertices [v].z
270+
), v);
271+
}
251272
}
252273

253274
var fbxMaterial = ExportMaterial (meshInfo.Material, fbxScene);
@@ -258,7 +279,7 @@ meshInfo.Vertices [v].z
258279
* or else they will be inverted on import
259280
* (due to the conversion from left to right handed coords)
260281
*/
261-
int[] fbxTriangles = new int[meshInfo.Triangles.Length];
282+
int[] unmergedTriangles = new int[meshInfo.Triangles.Length];
262283
int current = 0;
263284
for (int f = 0; f < meshInfo.Triangles.Length / 3; f++) {
264285
fbxMesh.BeginPolygon ();
@@ -267,17 +288,22 @@ meshInfo.Vertices [v].z
267288
// of 0,1,2, as this gets flipped back during import
268289
foreach (int val in new int[]{0,2,1}) {
269290
int tri = meshInfo.Triangles [3 * f + val];
291+
292+
// Save the triangle order (without merging vertices) so we
293+
// properly export UVs, normals, binormals, etc.
294+
unmergedTriangles [current] = tri;
295+
296+
if (weldVertices) {
297+
tri = ControlPointToIndex [meshInfo.Vertices [tri]];
298+
}
270299
fbxMesh.AddPolygon (tri);
271300

272-
// save the exported triangle order so we
273-
// properly export UVs
274-
fbxTriangles [current] = tri;
275301
current++;
276302
}
277303
fbxMesh.EndPolygon ();
278304
}
279305

280-
ExportUVsAndNormals (meshInfo, fbxMesh, fbxTriangles);
306+
ExportUVsAndNormals (meshInfo, fbxMesh, unmergedTriangles);
281307

282308
// set the fbxNode containing the mesh
283309
fbxNode.SetNodeAttribute (fbxMesh);
@@ -712,11 +738,6 @@ private MeshInfo GetMeshInfo (GameObject gameObject, bool requireRenderer = true
712738
/// </summary>
713739
public int NumTriangles { private set; get; }
714740

715-
/// <summary>
716-
/// Number of vertices
717-
/// </summary>
718-
public int NumVertices { private set; get; }
719-
720741
/// <summary>
721742
/// Clean up this class on garbage collection
722743
/// </summary>

0 commit comments

Comments
 (0)