@@ -57,7 +57,7 @@ public static ModelExporter Create ()
57
57
/// <summary>
58
58
/// Export the mesh's UVs using layer 0.
59
59
/// </summary>
60
- public void ExportUVsAndNormals ( MeshInfo mesh , FbxMesh fbxMesh , int [ ] fbxTriangles )
60
+ public void ExportUVsAndNormals ( MeshInfo mesh , FbxMesh fbxMesh , int [ ] unmergedTriangles )
61
61
{
62
62
// Set the normals on Layer 0.
63
63
FbxLayer fbxLayer = fbxMesh . GetLayer ( 0 /* default layer */ ) ;
@@ -67,23 +67,22 @@ public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriang
67
67
}
68
68
69
69
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 ) ;
74
71
75
72
fbxLayerElement . SetReferenceMode ( FbxLayerElement . EReferenceMode . eDirect ) ;
76
73
77
74
// Add one normal per each vertex face index (3 per triangle)
78
75
FbxLayerElementArray fbxElementArray = fbxLayerElement . GetDirectArray ( ) ;
79
76
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 ] ) ) ;
84
82
}
85
- fbxLayer . SetNormals ( fbxLayerElement ) ;
86
- }
83
+
84
+ fbxLayer . SetNormals ( fbxLayerElement ) ;
85
+ }
87
86
88
87
using ( var fbxLayerElement = FbxLayerElementUV . Create ( fbxMesh , "UVSet" ) ) {
89
88
fbxLayerElement . SetMappingMode ( FbxLayerElement . EMappingMode . eByPolygonVertex ) ;
@@ -92,20 +91,19 @@ public void ExportUVsAndNormals (MeshInfo mesh, FbxMesh fbxMesh, int[] fbxTriang
92
91
// set texture coordinates per vertex
93
92
FbxLayerElementArray fbxElementArray = fbxLayerElement . GetDirectArray ( ) ;
94
93
94
+ // TODO: only copy unique UVs into this array, and index appropriately
95
95
for ( int n = 0 ; n < mesh . UV . Length ; n ++ ) {
96
96
fbxElementArray . Add ( new FbxVector2 ( mesh . UV [ n ] [ 0 ] ,
97
97
mesh . UV [ n ] [ 1 ] ) ) ;
98
98
}
99
99
100
100
// For each face index, point to a texture uv
101
- var unityTriangles = mesh . Triangles ;
102
101
FbxLayerElementArray fbxIndexArray = fbxLayerElement . GetIndexArray ( ) ;
103
- fbxIndexArray . SetCount ( unityTriangles . Length ) ;
102
+ fbxIndexArray . SetCount ( unmergedTriangles . Length ) ;
104
103
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 ] ) ;
107
106
}
108
-
109
107
fbxLayer . SetUVs ( fbxLayerElement , FbxLayerElement . EType . eTextureDiffuse ) ;
110
108
}
111
109
}
@@ -223,31 +221,54 @@ public FbxSurfaceMaterial ExportMaterial (Material unityMaterial, FbxScene fbxSc
223
221
/// Unconditionally export this mesh object to the file.
224
222
/// We have decided; this mesh is definitely getting exported.
225
223
/// </summary>
226
- public void ExportMesh ( MeshInfo meshInfo , FbxNode fbxNode , FbxScene fbxScene )
224
+ public void ExportMesh ( MeshInfo meshInfo , FbxNode fbxNode , FbxScene fbxScene , bool weldVertices = true )
227
225
{
228
226
if ( ! meshInfo . IsValid )
229
227
return ;
230
228
231
229
NumMeshes ++ ;
232
230
NumTriangles += meshInfo . Triangles . Length / 3 ;
233
- NumVertices += meshInfo . VertexCount ;
234
231
235
232
// create the mesh structure.
236
233
FbxMesh fbxMesh = FbxMesh . Create ( fbxScene , "Scene" ) ;
237
234
238
235
// Create control points.
239
- int NumControlPoints = meshInfo . VertexCount ;
236
+ Dictionary < Vector3 , int > ControlPointToIndex = new Dictionary < Vector3 , int > ( ) ;
240
237
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 ;
242
245
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
+ }
251
272
}
252
273
253
274
var fbxMaterial = ExportMaterial ( meshInfo . Material , fbxScene ) ;
@@ -258,7 +279,7 @@ meshInfo.Vertices [v].z
258
279
* or else they will be inverted on import
259
280
* (due to the conversion from left to right handed coords)
260
281
*/
261
- int [ ] fbxTriangles = new int [ meshInfo . Triangles . Length ] ;
282
+ int [ ] unmergedTriangles = new int [ meshInfo . Triangles . Length ] ;
262
283
int current = 0 ;
263
284
for ( int f = 0 ; f < meshInfo . Triangles . Length / 3 ; f ++ ) {
264
285
fbxMesh . BeginPolygon ( ) ;
@@ -267,17 +288,22 @@ meshInfo.Vertices [v].z
267
288
// of 0,1,2, as this gets flipped back during import
268
289
foreach ( int val in new int [ ] { 0 , 2 , 1 } ) {
269
290
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
+ }
270
299
fbxMesh . AddPolygon ( tri ) ;
271
300
272
- // save the exported triangle order so we
273
- // properly export UVs
274
- fbxTriangles [ current ] = tri ;
275
301
current ++ ;
276
302
}
277
303
fbxMesh . EndPolygon ( ) ;
278
304
}
279
305
280
- ExportUVsAndNormals ( meshInfo , fbxMesh , fbxTriangles ) ;
306
+ ExportUVsAndNormals ( meshInfo , fbxMesh , unmergedTriangles ) ;
281
307
282
308
// set the fbxNode containing the mesh
283
309
fbxNode . SetNodeAttribute ( fbxMesh ) ;
@@ -712,11 +738,6 @@ private MeshInfo GetMeshInfo (GameObject gameObject, bool requireRenderer = true
712
738
/// </summary>
713
739
public int NumTriangles { private set ; get ; }
714
740
715
- /// <summary>
716
- /// Number of vertices
717
- /// </summary>
718
- public int NumVertices { private set ; get ; }
719
-
720
741
/// <summary>
721
742
/// Clean up this class on garbage collection
722
743
/// </summary>
0 commit comments